00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __INTERPOLATIONUTILS_HXX__
00021 #define __INTERPOLATIONUTILS_HXX__
00022
00023 #include "INTERPKERNELDefines.hxx"
00024 #include "InterpKernelException.hxx"
00025
00026 #include "NormalizedUnstructuredMesh.hxx"
00027
00028 #include <deque>
00029 #include <map>
00030 #include <cmath>
00031 #include <string>
00032 #include <vector>
00033 #include <algorithm>
00034 #include <iostream>
00035 #include <limits>
00036
00037 namespace INTERP_KERNEL
00038 {
00039 template<class ConnType, NumberingPolicy numPol>
00040 class OTT
00041 {
00042 };
00043
00044 template<class ConnType>
00045 class OTT<ConnType,ALL_C_MODE>
00046 {
00047 public:
00048 static ConnType indFC(ConnType i) { return i; }
00049 static ConnType ind2C(ConnType i) { return i; }
00050 static ConnType conn2C(ConnType i) { return i; }
00051 static ConnType coo2C(ConnType i) { return i; }
00052 };
00053
00054 template<class ConnType>
00055 class OTT<ConnType,ALL_FORTRAN_MODE>
00056 {
00057 public:
00058 static ConnType indFC(ConnType i) { return i+1; }
00059 static ConnType ind2C(ConnType i) { return i-1; }
00060 static ConnType conn2C(ConnType i) { return i-1; }
00061 static ConnType coo2C(ConnType i) { return i-1; }
00062 };
00063
00064
00065
00066
00067
00068 inline double Surf_Tri(const double* P_1,const double* P_2,const double* P_3)
00069 {
00070 double A=(P_3[1]-P_1[1])*(P_2[0]-P_1[0])-(P_2[1]-P_1[1])*(P_3[0]-P_1[0]);
00071 double Surface = 0.5*fabs(A);
00072 return Surface;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 inline double mon_determinant(const double* P_1,
00084 const double* P_2,
00085 const double* P_3)
00086 {
00087 double mon_det=(P_1[0]-P_3[0])*(P_2[1]-P_3[1])-(P_2[0]-P_3[0])*(P_1[1]-P_3[1]);
00088 return mon_det;
00089 }
00090
00091
00092
00093
00094 inline double norme_vecteur(const double* P_1,const double* P_2)
00095 {
00096 double X=P_1[0]-P_2[0];
00097 double Y=P_1[1]-P_2[1];
00098 double norme=sqrt(X*X+Y*Y);
00099 return norme;
00100 }
00101
00102
00103
00104
00105
00106 inline std::vector<double> calcul_cos_et_sin(const double* P_1,
00107 const double* P_2,
00108 const double* P_3)
00109 {
00110
00111 std::vector<double> Vect;
00112 double P1_P2=norme_vecteur(P_1,P_2);
00113 double P2_P3=norme_vecteur(P_2,P_3);
00114 double P3_P1=norme_vecteur(P_3,P_1);
00115
00116 double N=P1_P2*P1_P2+P3_P1*P3_P1-P2_P3*P2_P3;
00117 double D=2.0*P1_P2*P3_P1;
00118 double COS=N/D;
00119 if (COS>1.0) COS=1.0;
00120 if (COS<-1.0) COS=-1.0;
00121 Vect.push_back(COS);
00122 double V=mon_determinant(P_2,P_3,P_1);
00123 double D_1=P1_P2*P3_P1;
00124 double SIN=V/D_1;
00125 if (SIN>1.0) SIN=1.0;
00126 if (SIN<-1.0) SIN=-1.0;
00127 Vect.push_back(SIN);
00128
00129 return Vect;
00130
00131 }
00132
00140 template<int SPACEDIM>
00141 inline void fillDualCellOfTri(const double *triIn, double *quadOut)
00142 {
00143
00144 std::copy(triIn,triIn+SPACEDIM,quadOut);
00145 double tmp[SPACEDIM];
00146 std::transform(triIn,triIn+SPACEDIM,triIn+SPACEDIM,tmp,std::plus<double>());
00147
00148 std::transform(tmp,tmp+SPACEDIM,quadOut+SPACEDIM,std::bind2nd(std::multiplies<double>(),0.5));
00149 std::transform(tmp,tmp+SPACEDIM,triIn+2*SPACEDIM,tmp,std::plus<double>());
00150
00151 std::transform(tmp,tmp+SPACEDIM,quadOut+2*SPACEDIM,std::bind2nd(std::multiplies<double>(),1/3.));
00152
00153 std::transform(triIn,triIn+SPACEDIM,triIn+2*SPACEDIM,tmp,std::plus<double>());
00154 std::transform(tmp,tmp+SPACEDIM,quadOut+3*SPACEDIM,std::bind2nd(std::multiplies<double>(),0.5));
00155 }
00156
00164 template<int SPACEDIM>
00165 inline void fillDualCellOfPolyg(const double *polygIn, int nPtsPolygonIn, double *polygOut)
00166 {
00167
00168 std::copy(polygIn,polygIn+SPACEDIM,polygOut);
00169 std::transform(polygIn,polygIn+SPACEDIM,polygIn+SPACEDIM,polygOut+SPACEDIM,std::plus<double>());
00170
00171 std::transform(polygOut+SPACEDIM,polygOut+2*SPACEDIM,polygOut+SPACEDIM,std::bind2nd(std::multiplies<double>(),0.5));
00172 double tmp[SPACEDIM];
00173
00174 for(int i=0;i<nPtsPolygonIn-2;i++)
00175 {
00176 std::transform(polygIn,polygIn+SPACEDIM,polygIn+(i+2)*SPACEDIM,tmp,std::plus<double>());
00177 std::transform(tmp,tmp+SPACEDIM,polygOut+(2*i+3)*SPACEDIM,std::bind2nd(std::multiplies<double>(),0.5));
00178 std::transform(polygIn+(i+1)*SPACEDIM,polygIn+(i+2)*SPACEDIM,tmp,tmp,std::plus<double>());
00179 std::transform(tmp,tmp+SPACEDIM,polygOut+(2*i+2)*SPACEDIM,std::bind2nd(std::multiplies<double>(),1./3.));
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 inline std::vector<double> bary_poly(const std::vector<double>& V)
00190 {
00191 std::vector<double> Bary;
00192 long taille=V.size();
00193 double x=0;
00194 double y=0;
00195
00196 for(long i=0;i<taille/2;i++)
00197 {
00198 x=x+V[2*i];
00199 y=y+V[2*i+1];
00200 }
00201 double A=2*x/taille;
00202 double B=2*y/taille;
00203 Bary.push_back(A);
00204 Bary.push_back(B);
00205
00206
00207 return Bary;
00208 }
00209
00213 inline double computeTria6RefBase(const double *coeffs, const double *pos)
00214 {
00215 return coeffs[0]+coeffs[1]*pos[0]+coeffs[2]*pos[1]+coeffs[3]*pos[0]*pos[0]+coeffs[4]*pos[0]*pos[1]+coeffs[5]*pos[1]*pos[1];
00216 }
00217
00221 inline void computeWeightedCoeffsInTria6FromRefBase(const double *refCoo, double *weightedPos)
00222 {
00223 weightedPos[0]=(1.-refCoo[0]-refCoo[1])*(1.-2*refCoo[0]-2.*refCoo[1]);
00224 weightedPos[1]=refCoo[0]*(2.*refCoo[0]-1.);
00225 weightedPos[2]=refCoo[1]*(2.*refCoo[1]-1.);
00226 weightedPos[3]=4.*refCoo[0]*(1.-refCoo[0]-refCoo[1]);
00227 weightedPos[4]=4.*refCoo[0]*refCoo[1];
00228 weightedPos[5]=4.*refCoo[1]*(1.-refCoo[0]-refCoo[1]);
00229 }
00230
00234 inline double computeTetra10RefBase(const double *coeffs, const double *pos)
00235 {
00236 return coeffs[0]+coeffs[1]*pos[0]+coeffs[2]*pos[1]+coeffs[3]*pos[2]+
00237 coeffs[4]*pos[0]*pos[0]+coeffs[5]*pos[0]*pos[1]+coeffs[6]*pos[0]*pos[2]+
00238 coeffs[7]*pos[1]*pos[1]+coeffs[8]*pos[1]*pos[2]+coeffs[9]*pos[2]*pos[2];
00239 }
00240
00244 inline void computeWeightedCoeffsInTetra10FromRefBase(const double *refCoo, double *weightedPos)
00245 {
00246
00247
00248
00249 weightedPos[0]=(-2.*(refCoo[0]+refCoo[1]+refCoo[2])+1)*(1-refCoo[0]-refCoo[1]-refCoo[2]);
00250 weightedPos[1]=(2.*refCoo[0]-1.)*refCoo[0];
00251 weightedPos[2]=(2.*refCoo[1]-1.)*refCoo[1];
00252 weightedPos[3]=(2.*refCoo[2]-1.)*refCoo[2];
00253 weightedPos[4]=4.*(1-refCoo[0]-refCoo[1]-refCoo[2])*refCoo[0];
00254 weightedPos[5]=4.*refCoo[0]*refCoo[1];
00255 weightedPos[6]=4.*(1-refCoo[0]-refCoo[1]-refCoo[2])*refCoo[1];
00256 weightedPos[7]=4.*(1-refCoo[0]-refCoo[1]-refCoo[2])*refCoo[2];
00257 weightedPos[8]=4.*refCoo[0]*refCoo[2];
00258 weightedPos[9]=4.*refCoo[1]*refCoo[2];
00259 }
00260
00267 template<unsigned nbRow>
00268 bool solveSystemOfEquations(double M[nbRow][nbRow+1], double* sol)
00269 {
00270 const int nbCol=nbRow+1;
00271
00272
00273
00274 int iR[nbRow];
00275 for ( int i = 0; i < (int) nbRow; ++i )
00276 iR[i] = i;
00277 for ( int i = 0; i < (int)(nbRow-1); ++i )
00278 {
00279
00280 double max = std::fabs( M[ iR[i] ][i] );
00281 for ( int r = i+1; r < (int)nbRow; ++r )
00282 {
00283 double m = std::fabs( M[ iR[r] ][i] );
00284 if ( m > max )
00285 {
00286 max = m;
00287 std::swap( iR[r], iR[i] );
00288 }
00289 }
00290 if ( max < std::numeric_limits<double>::min() )
00291 {
00292
00293 return false;
00294 }
00295
00296 double* tUpRow = M[ iR[i] ];
00297 for ( int r = i+1; r < (int)nbRow; ++r )
00298 {
00299 double* mRow = M[ iR[r] ];
00300 double coef = mRow[ i ] / tUpRow[ i ];
00301 for ( int c = i+1; c < nbCol; ++c )
00302 mRow[ c ] -= tUpRow[ c ] * coef;
00303 }
00304 }
00305 double* mRow = M[ iR[nbRow-1] ];
00306 if ( std::fabs( mRow[ nbRow-1 ] ) < std::numeric_limits<double>::min() )
00307 {
00308
00309 return false;
00310 }
00311 mRow[ nbRow ] /= mRow[ nbRow-1 ];
00312
00313
00314
00315 sol[ nbRow-1 ] = mRow[ nbRow ];
00316
00317 for ( int i = nbRow-2; i+1; --i )
00318 {
00319 mRow = M[ iR[i] ];
00320 sol[ i ] = mRow[ nbRow ];
00321 for ( int j = nbRow-1; j > i; --j )
00322 sol[ i ] -= sol[j]*mRow[ j ];
00323 sol[ i ] /= mRow[ i ];
00324 }
00325
00326 return true;
00327 }
00328
00329
00336 template<unsigned SZ, unsigned NB_OF_RES>
00337 bool solveSystemOfEquations2(const double *matrix, double *solutions, double eps)
00338 {
00339 unsigned k,j;
00340 int nr,n,m,np;
00341 double s,g;
00342 int mb;
00343
00344 double B[SZ*(SZ+NB_OF_RES)];
00345 std::copy(matrix,matrix+SZ*(SZ+NB_OF_RES),B);
00346
00347 nr=SZ+NB_OF_RES;
00348 for(k=0;k<SZ;k++)
00349 {
00350 np=nr*k+k;
00351 if(fabs(B[np])<eps)
00352 {
00353 n=k;
00354 do
00355 {
00356 n++;
00357 if(fabs(B[nr*k+n])>eps)
00358 {
00359 for(m=0;m<nr;m++)
00360 std::swap(B[nr*k+m],B[nr*n+m]);
00361 }
00362 }
00363 while (n<(int)SZ);
00364 }
00365 s=B[np];
00366 std::transform(B+k*nr,B+(k+1)*nr,B+k*nr,std::bind2nd(std::divides<double>(),s));
00367 for(j=0;j<SZ;j++)
00368 {
00369 if(j!=k)
00370 {
00371 g=B[j*nr+k];
00372 for(mb=k;mb<nr;mb++)
00373 B[j*nr+mb]-=B[k*nr+mb]*g;
00374 }
00375 }
00376 }
00377 for(j=0;j<NB_OF_RES;j++)
00378 for(k=0;k<SZ;k++)
00379 solutions[j*SZ+k]=B[nr*k+SZ+j];
00380
00381 return true;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 template<int SPACEDIM>
00391 inline void barycentric_coords(const double* triaCoords, const double* p, double* bc)
00392 {
00393
00394 double
00395 T11 = triaCoords[0]-triaCoords[2*SPACEDIM], T12 = triaCoords[SPACEDIM]-triaCoords[2*SPACEDIM],
00396 T21 = triaCoords[1]-triaCoords[2*SPACEDIM+1], T22 = triaCoords[SPACEDIM+1]-triaCoords[2*SPACEDIM+1];
00397
00398 double Tdet = T11*T22 - T12*T21;
00399 if ( fabs( Tdet ) < std::numeric_limits<double>::min() ) {
00400 bc[0]=1; bc[1]=0; bc[2]=0;
00401 return;
00402 }
00403
00404 double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
00405
00406 double r11 = p[0]-triaCoords[2*SPACEDIM], r12 = p[1]-triaCoords[2*SPACEDIM+1];
00407
00408 bc[0] = (t11 * r11 + t12 * r12)/Tdet;
00409 bc[1] = (t21 * r11 + t22 * r12)/Tdet;
00410 bc[2] = 1. - bc[0] - bc[1];
00411 }
00412
00420 inline void barycentric_coords(const std::vector<const double*>& n, const double *p, double *bc)
00421 {
00422 enum { _X, _Y, _Z };
00423 switch(n.size())
00424 {
00425 case 3:
00426 {
00427
00428 double
00429 T11 = n[0][_X]-n[2][_X], T12 = n[1][_X]-n[2][_X],
00430 T21 = n[0][_Y]-n[2][_Y], T22 = n[1][_Y]-n[2][_Y];
00431
00432 double Tdet = T11*T22 - T12*T21;
00433 if ( std::fabs( Tdet ) < std::numeric_limits<double>::min() )
00434 {
00435 bc[0]=1; bc[1]=bc[2]=0;
00436 return;
00437 }
00438
00439 double t11 = T22, t12 = -T12, t21 = -T21, t22 = T11;
00440
00441 double r11 = p[_X]-n[2][_X], r12 = p[_Y]-n[2][_Y];
00442
00443 bc[0] = (t11 * r11 + t12 * r12)/Tdet;
00444 bc[1] = (t21 * r11 + t22 * r12)/Tdet;
00445 bc[2] = 1. - bc[0] - bc[1];
00446 break;
00447 }
00448 case 4:
00449 {
00450
00451
00452
00453
00454
00455 double T[3][4]=
00456 {{ n[0][_X]-n[3][_X], n[1][_X]-n[3][_X], n[2][_X]-n[3][_X], p[_X]-n[3][_X] },
00457 { n[0][_Y]-n[3][_Y], n[1][_Y]-n[3][_Y], n[2][_Y]-n[3][_Y], p[_Y]-n[3][_Y] },
00458 { n[0][_Z]-n[3][_Z], n[1][_Z]-n[3][_Z], n[2][_Z]-n[3][_Z], p[_Z]-n[3][_Z] }};
00459
00460 if ( !solveSystemOfEquations<3>( T, bc ) )
00461 bc[0]=1., bc[1] = bc[2] = bc[3] = 0;
00462 else
00463 bc[ 3 ] = 1. - bc[0] - bc[1] - bc[2];
00464 break;
00465 }
00466 case 6:
00467 {
00468
00469 double matrix2[48]={1., 0., 0., 0., 0., 0., 0., 0.,
00470 1., 0., 0., 0., 0., 0., 1., 0.,
00471 1., 0., 0., 0., 0., 0., 0., 1.,
00472 1., 0., 0., 0., 0., 0., 0.5, 0.,
00473 1., 0., 0., 0., 0., 0., 0.5, 0.5,
00474 1., 0., 0., 0., 0., 0., 0.,0.5};
00475 for(int i=0;i<6;i++)
00476 {
00477 matrix2[8*i+1]=n[i][0];
00478 matrix2[8*i+2]=n[i][1];
00479 matrix2[8*i+3]=n[i][0]*n[i][0];
00480 matrix2[8*i+4]=n[i][0]*n[i][1];
00481 matrix2[8*i+5]=n[i][1]*n[i][1];
00482 }
00483 double res[12];
00484 solveSystemOfEquations2<6,2>(matrix2,res,std::numeric_limits<double>::min());
00485 double refCoo[2];
00486 refCoo[0]=computeTria6RefBase(res,p);
00487 refCoo[1]=computeTria6RefBase(res+6,p);
00488 computeWeightedCoeffsInTria6FromRefBase(refCoo,bc);
00489 break;
00490 }
00491 case 10:
00492 {
00493 double matrix2[130]={1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
00494 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,
00495 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
00496 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,
00497 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.5, 0., 0.,
00498 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.5, 0.5, 0.,
00499 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,0.5, 0.,
00500 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.5,
00501 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.5, 0., 0.5,
00502 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.5, 0.5};
00503 for(int i=0;i<10;i++)
00504 {
00505 matrix2[13*i+1]=n[i][0];
00506 matrix2[13*i+2]=n[i][1];
00507 matrix2[13*i+3]=n[i][2];
00508 matrix2[13*i+4]=n[i][0]*n[i][0];
00509 matrix2[13*i+5]=n[i][0]*n[i][1];
00510 matrix2[13*i+6]=n[i][0]*n[i][2];
00511 matrix2[13*i+7]=n[i][1]*n[i][1];
00512 matrix2[13*i+8]=n[i][1]*n[i][2];
00513 matrix2[13*i+9]=n[i][2]*n[i][2];
00514 }
00515 double res[30];
00516 solveSystemOfEquations2<10,3>(matrix2,res,std::numeric_limits<double>::min());
00517 double refCoo[3];
00518 refCoo[0]=computeTetra10RefBase(res,p);
00519 refCoo[1]=computeTetra10RefBase(res+10,p);
00520 refCoo[2]=computeTetra10RefBase(res+20,p);
00521 computeWeightedCoeffsInTetra10FromRefBase(refCoo,bc);
00522 break;
00523 }
00524 default:
00525 throw INTERP_KERNEL::Exception("INTERP_KERNEL::barycentric_coords : unrecognized simplex !");
00526 }
00527 }
00528
00529
00530
00531
00532
00533 inline double Surf_Poly(const std::vector<double>& Poly)
00534 {
00535
00536 double Surface=0;
00537 for(unsigned long i=0; i<(Poly.size())/2-2; i++)
00538 {
00539 double Surf=Surf_Tri( &Poly[0],&Poly[2*(i+1)],&Poly[2*(i+2)] );
00540 Surface=Surface + Surf ;
00541 }
00542 return Surface ;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 inline bool point_dans_triangle(const double* P_0,const double* P_1,
00552 const double* P_2,const double* P_3,
00553 double eps)
00554 {
00555
00556 bool A=false;
00557 double det_1=mon_determinant(P_1,P_3,P_0);
00558 double det_2=mon_determinant(P_3,P_2,P_0);
00559 double det_3=mon_determinant(P_2,P_1,P_0);
00560 if( (det_1>=-eps && det_2>=-eps && det_3>=-eps) || (det_1<=eps && det_2<=eps && det_3<=eps) )
00561 {
00562 A=true;
00563 }
00564
00565 return A;
00566 }
00567
00568
00569
00570
00571
00572
00573 inline void verif_point_dans_vect(const double* P, std::vector<double>& V, double absolute_precision )
00574 {
00575 long taille=V.size();
00576 bool isPresent=false;
00577 for(long i=0;i<taille/2;i++)
00578 {
00579 if (sqrt(((P[0]-V[2*i])*(P[0]-V[2*i])+(P[1]-V[2*i+1])*(P[1]-V[2*i+1])))<absolute_precision)
00580 isPresent=true;
00581
00582 }
00583 if(!isPresent)
00584 {
00585
00586 V.push_back(P[0]);
00587 V.push_back(P[1]);
00588 }
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 inline void rajou_sommet_triangl(const double* P_1,const double* P_2,const double* P_3,
00600 const double* P_4,const double* P_5,const double* P_6,
00601 std::vector<double>& V, double dim_caracteristic, double precision)
00602 {
00603
00604 double absolute_precision = precision*dim_caracteristic;
00605 bool A_1=INTERP_KERNEL::point_dans_triangle(P_1,P_4,P_5,P_6,absolute_precision);
00606 if(A_1)
00607 verif_point_dans_vect(P_1,V,absolute_precision);
00608 bool A_2=INTERP_KERNEL::point_dans_triangle(P_2,P_4,P_5,P_6,absolute_precision);
00609 if(A_2)
00610 verif_point_dans_vect(P_2,V,absolute_precision);
00611 bool A_3=INTERP_KERNEL::point_dans_triangle(P_3,P_4,P_5,P_6,absolute_precision);
00612 if(A_3)
00613 verif_point_dans_vect(P_3,V,absolute_precision);
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623 inline void inters_de_segment(const double * P_1,const double * P_2,
00624 const double * P_3,const double * P_4,
00625 std::vector<double>& Vect,
00626 double dim_caracteristic, double precision)
00627 {
00628
00629 double det=(P_2[0]-P_1[0])*(P_4[1]-P_3[1])-(P_4[0]-P_3[0])*(P_2[1]-P_1[1]);
00630
00631 double absolute_precision = dim_caracteristic*precision;
00632 if(fabs(det)>absolute_precision)
00633 {
00634 double k_1=-((P_3[1]-P_4[1])*(P_3[0]-P_1[0])+(P_4[0]-P_3[0])*(P_3[1]-P_1[1]))/det;
00635
00636 if (k_1 >= -absolute_precision && k_1 <= 1+absolute_precision)
00637
00638 {
00639 double k_2= ((P_1[1]-P_2[1])*(P_1[0]-P_3[0])+(P_2[0]-P_1[0])*(P_1[1]-P_3[1]))/det;
00640
00641 if (k_2 >= -absolute_precision && k_2 <= 1+absolute_precision)
00642
00643 {
00644 double P_0[2];
00645 P_0[0]=P_1[0]+k_1*(P_2[0]-P_1[0]);
00646 P_0[1]=P_1[1]+k_1*(P_2[1]-P_1[1]);
00647 verif_point_dans_vect(P_0,Vect,absolute_precision);
00648 }
00649 }
00650 }
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 inline void intersec_de_triangle(const double* P_1,const double* P_2, const double* P_3,
00662 const double* P_4,const double* P_5,const double* P_6,
00663 std::vector<double>& Vect, double dim_caracteristic, double precision)
00664 {
00665 inters_de_segment(P_1,P_2,P_4,P_5,Vect, dim_caracteristic, precision);
00666 inters_de_segment(P_1,P_2,P_5,P_6,Vect, dim_caracteristic, precision);
00667 inters_de_segment(P_1,P_2,P_6,P_4,Vect, dim_caracteristic, precision);
00668 inters_de_segment(P_2,P_3,P_4,P_5,Vect, dim_caracteristic, precision);
00669 inters_de_segment(P_2,P_3,P_5,P_6,Vect, dim_caracteristic, precision);
00670 inters_de_segment(P_2,P_3,P_6,P_4,Vect, dim_caracteristic, precision);
00671 inters_de_segment(P_3,P_1,P_4,P_5,Vect, dim_caracteristic, precision);
00672 inters_de_segment(P_3,P_1,P_5,P_6,Vect, dim_caracteristic, precision);
00673 inters_de_segment(P_3,P_1,P_6,P_4,Vect, dim_caracteristic, precision);
00674 rajou_sommet_triangl(P_1,P_2,P_3,P_4,P_5,P_6,Vect, dim_caracteristic, precision);
00675 rajou_sommet_triangl(P_4,P_5,P_6,P_1,P_2,P_3,Vect, dim_caracteristic, precision);
00676 }
00677
00678
00679
00680
00681
00682
00683 inline void verif_maill_dans_vect(int Num, std::vector<int>& V)
00684 {
00685 long taille=V.size();
00686 int A=0;
00687 for(long i=0;i<taille;i++)
00688 {
00689 if(Num==V[i])
00690 {
00691 A=1;
00692 break;
00693 }
00694 }
00695 if(A==0)
00696 {V.push_back(Num); }
00697 }
00698
00701 class AngleLess
00702 {
00703 public:
00704 bool operator()(std::pair<double,double>theta1, std::pair<double,double> theta2)
00705 {
00706 double norm1 = sqrt(theta1.first*theta1.first +theta1.second*theta1.second);
00707 double norm2 = sqrt(theta2.first*theta2.first +theta2.second*theta2.second);
00708
00709 double epsilon = 1.e-12;
00710
00711 if( norm1 < epsilon || norm2 < epsilon )
00712 std::cout << "Warning InterpolationUtils.hxx: AngleLess : Vector with zero norm, cannot define the angle !!!! " << std::endl;
00713
00714 return theta1.second*(norm2 + theta2.first) < theta2.second*(norm1 + theta1.first);
00715
00716 }
00717 };
00718
00719
00720
00721
00722
00723
00724
00725 inline std::vector<double> reconstruct_polygon(const std::vector<double>& V)
00726 {
00727
00728 int taille=V.size();
00729
00730
00731
00732 if(taille<=6)
00733 {return V;}
00734 else
00735 {
00736 double *COS=new double[taille/2];
00737 double *SIN=new double[taille/2];
00738
00739 std::vector<double> Bary=bary_poly(V);
00740 COS[0]=1.0;
00741 SIN[0]=0.0;
00742
00743 for(int i=0; i<taille/2-1;i++)
00744 {
00745 std::vector<double> Trigo=calcul_cos_et_sin(&Bary[0],&V[0],&V[2*(i+1)]);
00746 COS[i+1]=Trigo[0];
00747 SIN[i+1]=Trigo[1];
00748
00749
00750
00751
00752 }
00753
00754
00755 std::vector<double> Pt_ordonne;
00756 Pt_ordonne.reserve(taille);
00757
00758 std::multimap<std::pair<double,double>,int, AngleLess> CosSin;
00759 for(int i=0;i<taille/2;i++)
00760 {
00761
00762 CosSin.insert(std::make_pair(std::make_pair(SIN[i],COS[i]),i));
00763 }
00764
00765 std::multimap<std::pair<double,double>,int, AngleLess>::iterator micossin;
00766
00767
00768
00769
00770
00771
00772 for(micossin=CosSin.begin();micossin!=CosSin.end();micossin++)
00773 {
00774 int j=(*micossin).second;
00775 Pt_ordonne.push_back(V[2*j]);
00776 Pt_ordonne.push_back(V[2*j+1]);
00777 }
00778 delete [] COS;
00779 delete [] SIN;
00780
00781 return Pt_ordonne;
00782 }
00783 }
00784
00785 template<int DIM, NumberingPolicy numPol, class MyMeshType>
00786 inline void getElemBB(double* bb, const double *coordsOfMesh, int iP, int nb_nodes)
00787 {
00788 bb[0]=std::numeric_limits<double>::max();
00789 bb[1]=-std::numeric_limits<double>::max();
00790 bb[2]=std::numeric_limits<double>::max();
00791 bb[3]=-std::numeric_limits<double>::max();
00792 bb[4]=std::numeric_limits<double>::max();
00793 bb[5]=-std::numeric_limits<double>::max();
00794
00795 for (int i=0; i<nb_nodes; i++)
00796 {
00797 double x = coordsOfMesh[3*(iP+i)];
00798 double y = coordsOfMesh[3*(iP+i)+1];
00799 double z = coordsOfMesh[3*(iP+i)+2];
00800 bb[0]=(x<bb[0])?x:bb[0];
00801 bb[1]=(x>bb[1])?x:bb[1];
00802 bb[2]=(y<bb[2])?y:bb[2];
00803 bb[3]=(y>bb[3])?y:bb[3];
00804 bb[4]=(z<bb[4])?z:bb[4];
00805 bb[5]=(z>bb[5])?z:bb[5];
00806 }
00807 }
00808
00809
00810
00811
00812 template<int dim>
00813 inline double dotprod( const double * a, const double * b)
00814 {
00815 double result=0;
00816 for(int idim = 0; idim < dim ; idim++) result += a[idim]*b[idim];
00817 return result;
00818 }
00819
00820
00821
00822 template<int dim>
00823 inline double norm(const double * v)
00824 {
00825 double result =0;
00826 for(int idim =0; idim<dim; idim++) result+=v[idim]*v[idim];
00827 return sqrt(result);
00828 }
00829
00830
00831
00832 template<int dim>
00833 inline double distance2( const double * a, const double * b)
00834 {
00835 double result =0;
00836 for(int idim =0; idim<dim; idim++) result+=(a[idim]-b[idim])*(a[idim]-b[idim]);
00837 return result;
00838 }
00839 template<class T, int dim>
00840 inline double distance2( T * a, int inda, T * b, int indb)
00841 {
00842 double result =0;
00843 for(int idim =0; idim<dim; idim++) result += ((*a)[inda+idim] - (*b)[indb+idim])* ((*a)[inda+idim] - (*b)[indb+idim]);
00844 return result;
00845 }
00846
00847
00848
00849 inline double determinant ( double * a, double * b)
00850 {
00851 return a[0]*b[1]-a[1]*b[0];
00852 }
00853 inline double determinant ( double * a, double * b, double * c)
00854 {
00855 return a[0]*determinant(b+1,c+1)-b[0]*determinant(a+1,c+1)+c[0]*determinant(a+1,b+1);
00856 }
00857
00858
00859
00860
00861
00862 template<int dim> inline void crossprod( const double * A, const double * B, const double * C, double * V);
00863
00864 template<> inline
00865 void crossprod<2>( const double * A, const double * B, const double * C, double * V)
00866 {
00867 double AB[2];
00868 double AC[2];
00869 for(int idim =0; idim<2; idim++) AB[idim] = B[idim]-A[idim];
00870 for(int idim =0; idim<2; idim++) AC[idim] = C[idim]-A[idim];
00871
00872 V[0]=determinant(AB,AC);
00873 V[1]=0;
00874 }
00875 template<> inline
00876 void crossprod<3>( const double * A, const double * B, const double * C, double * V)
00877 {
00878 double AB[3];
00879 double AC[3];
00880 for(int idim =0; idim<3; idim++) AB[idim] = B[idim]-A[idim];
00881 for(int idim =0; idim<3; idim++) AC[idim] = C[idim]-A[idim];
00882
00883 V[0]=AB[1]*AC[2]-AB[2]*AC[1];
00884 V[1]=-AB[0]*AC[2]+AB[2]*AC[0];
00885 V[2]=AB[0]*AC[1]-AB[1]*AC[0];
00886 }
00887 template<> inline
00888 void crossprod<1>( const double * A, const double * B, const double * C, double * V)
00889 {
00890
00891 }
00892
00893
00894
00895
00896
00897 template<int dim> inline double check_inside(const double* A,const double* B,const double* C,const double* D,
00898 const double* E,double* ABC, double* ADE)
00899 {
00900 crossprod<dim>(A,B,C,ABC);
00901 crossprod<dim>(A,D,E,ADE);
00902 return dotprod<dim>(ABC,ADE);
00903 }
00904
00905
00906
00907
00908
00909 template<int dim> inline double angle(const double * A, const double * B, const double * C, double * n)
00910 {
00911 double AB[dim];
00912 double AC[dim];
00913 double orthAB[dim];
00914
00915 for(int idim =0; idim<dim; idim++) AB[idim] = B[idim]-A[idim];
00916 for(int idim =0; idim<dim; idim++) AC[idim] = C[idim]-A[idim];
00917
00918 double normAB= norm<dim>(AB);
00919 for(int idim =0; idim<dim; idim++) AB[idim]/=normAB;
00920
00921 double normAC= norm<dim>(AC);
00922 double AB_dot_AC=dotprod<dim>(AB,AC);
00923 for(int idim =0; idim<dim; idim++) orthAB[idim] = AC[idim]-AB_dot_AC*AB[idim];
00924
00925 double denom= normAC+AB_dot_AC;
00926 double numer=norm<dim>(orthAB);
00927
00928 return 2*atan2(numer,denom);
00929 }
00930
00931
00932
00933
00934 template<int dim> inline double direct_frame(const double * A, const double * B, const double * C, double * n);
00935 template<> inline
00936 double direct_frame<2>(const double * A, const double * B, const double * C, double * n)
00937 {
00938 double AB[2];
00939 double AC[2];
00940 for(int idim =0; idim<2; idim++) AB[idim] = B[idim]-A[idim];
00941 for(int idim =0; idim<2; idim++) AC[idim] = C[idim]-A[idim];
00942
00943 return determinant(AB,AC)*n[0];
00944 }
00945 template<> inline
00946 double direct_frame<3>(const double * A, const double * B, const double * C, double * n)
00947 {
00948 double AB[3];
00949 double AC[3];
00950 for(int idim =0; idim<3; idim++) AB[idim] = B[idim]-A[idim];
00951 for(int idim =0; idim<3; idim++) AC[idim] = C[idim]-A[idim];
00952
00953 return determinant(AB,AC,n)>0;
00954 }
00955
00956
00957
00958
00959
00960
00961 template<int DIM> inline void intersec_de_polygone(const double * Coords_A, const double * Coords_B,
00962 int nb_NodesA, int nb_NodesB,
00963 std::vector<double>& inter,
00964 double dim_caracteristic, double precision)
00965 {
00966 for(int i_A = 1; i_A<nb_NodesA-1; i_A++)
00967 {
00968 for(int i_B = 1; i_B<nb_NodesB-1; i_B++)
00969 {
00970 INTERP_KERNEL::intersec_de_triangle(&Coords_A[0],&Coords_A[DIM*i_A],&Coords_A[DIM*(i_A+1)],
00971 &Coords_B[0],&Coords_B[DIM*i_B],&Coords_B[DIM*(i_B+1)],
00972 inter, dim_caracteristic, precision);
00973 }
00974 }
00975 int nb_inter=((int)inter.size())/DIM;
00976 if(nb_inter >3) inter=INTERP_KERNEL::reconstruct_polygon(inter);
00977 }
00978
00979
00980
00981
00982
00983 template<int DIM> inline double polygon_area(std::vector<double>& inter)
00984 {
00985 double result=0.;
00986 double area[DIM];
00987
00988 for(int i = 1; i<(int)inter.size()/DIM-1; i++)
00989 {
00990 INTERP_KERNEL::crossprod<DIM>(&inter[0],&inter[DIM*i],&inter[DIM*(i+1)],area);
00991 result +=0.5*norm<DIM>(area);
00992 }
00993 return result;
00994 }
00995
00996 template<int DIM> inline double polygon_area(std::deque<double>& inter)
00997 {
00998 double result=0.;
00999 double area[DIM];
01000
01001 for(int i = 1; i<(int)inter.size()/DIM-1; i++)
01002 {
01003 INTERP_KERNEL::crossprod<DIM>(&inter[0],&inter[DIM*i],&inter[DIM*(i+1)],area);
01004 result +=0.5*norm<DIM>(area);
01005 }
01006 return result;
01007 }
01008
01010 inline double triple_product(const double* A, const double*B, const double*C, const double*X)
01011 {
01012 double XA[3];
01013 XA[0]=A[0]-X[0];
01014 XA[1]=A[1]-X[1];
01015 XA[2]=A[2]-X[2];
01016 double XB[3];
01017 XB[0]=B[0]-X[0];
01018 XB[1]=B[1]-X[1];
01019 XB[2]=B[2]-X[2];
01020 double XC[3];
01021 XC[0]=C[0]-X[0];
01022 XC[1]=C[1]-X[1];
01023 XC[2]=C[2]-X[2];
01024
01025 return
01026 (XA[1]*XB[2]-XA[2]*XB[1])*XC[0]+
01027 (XA[2]*XB[0]-XA[0]*XB[2])*XC[1]+
01028 (XA[0]*XB[1]-XA[1]*XB[0])*XC[2];
01029 }
01030
01034 template<class T, int dim>
01035 bool checkEqualPolygonsOneDirection(T * L1, T * L2, int size1, int size2, int istart1, int istart2, double epsilon, int sign)
01036 {
01037 int i1 = istart1;
01038 int i2 = istart2;
01039 int i1next = ( i1 + 1 ) % size1;
01040 int i2next = ( i2 + sign +size2) % size2;
01041
01042 while(true)
01043 {
01044 while( i1next!=istart1 && distance2<T,dim>(L1,i1*dim, L1,i1next*dim) < epsilon ) i1next = ( i1next + 1 ) % size1;
01045 while( i2next!=istart2 && distance2<T,dim>(L2,i2*dim, L2,i2next*dim) < epsilon ) i2next = ( i2next + sign +size2 ) % size2;
01046
01047 if(i1next == istart1)
01048 {
01049 if(i2next == istart2)
01050 return true;
01051 else return false;
01052 }
01053 else
01054 if(i2next == istart2)
01055 return false;
01056 else
01057 {
01058 if(distance2<T,dim>(L1,i1next*dim, L2,i2next*dim) > epsilon )
01059 return false;
01060 else
01061 {
01062 i1 = i1next;
01063 i2 = i2next;
01064 i1next = ( i1 + 1 ) % size1;
01065 i2next = ( i2 + sign + size2 ) % size2;
01066 }
01067 }
01068 }
01069 }
01070
01073 template<class T, int dim>
01074 bool checkEqualPolygons(T * L1, T * L2, double epsilon)
01075 {
01076 if(L1==NULL || L2==NULL)
01077 {
01078 std::cout << "Warning InterpolationUtils.hxx:checkEqualPolygonsPointer: Null pointer " << std::endl;
01079 throw(Exception("big error: not closed polygon..."));
01080 }
01081
01082 int size1 = (*L1).size()/dim;
01083 int size2 = (*L2).size()/dim;
01084 int istart1 = 0;
01085 int istart2 = 0;
01086
01087 while( istart2 < size2 && distance2<T,dim>(L1,istart1*dim, L2,istart2*dim) > epsilon ) istart2++;
01088
01089 if(istart2 == size2)
01090 {
01091 return (size1 == 0) && (size2 == 0);
01092 }
01093 else
01094 return checkEqualPolygonsOneDirection<T,dim>( L1, L2, size1, size2, istart1, istart2, epsilon, 1)
01095 || checkEqualPolygonsOneDirection<T,dim>( L1, L2, size1, size2, istart1, istart2, epsilon, -1);
01096
01097 }
01098 }
01099
01100
01101 #endif