00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifdef _MSC_VER
00028 #pragma warning(disable:4786)
00029 #endif
00030
00031 #include "SMDS_VolumeTool.hxx"
00032
00033 #include "SMDS_MeshElement.hxx"
00034 #include "SMDS_MeshNode.hxx"
00035 #include "SMDS_VtkVolume.hxx"
00036 #include "SMDS_Mesh.hxx"
00037
00038 #include "utilities.h"
00039
00040 #include <map>
00041 #include <float.h>
00042 #include <math.h>
00043
00044 using namespace std;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 static int Tetra_F [4][4] = {
00066 { 0, 1, 2, 0 },
00067 { 0, 3, 1, 0 },
00068 { 1, 3, 2, 1 },
00069 { 0, 2, 3, 0 }};
00070 static int Tetra_R [4][4] = {
00071 { 0, 1, 2, 0 },
00072 { 0, 1, 3, 0 },
00073 { 1, 2, 3, 1 },
00074 { 0, 3, 2, 0 }};
00075 static int Tetra_RE [4][4] = {
00076 { 0, 2, 1, 0 },
00077 { 0, 1, 3, 0 },
00078 { 1, 2, 3, 1 },
00079 { 0, 3, 2, 0 }};
00080 static int Tetra_nbN [] = { 3, 3, 3, 3 };
00081
00082
00083
00084
00085 static int Pyramid_F [5][5] = {
00086 { 0, 1, 2, 3, 0 },
00087 { 0, 4, 1, 0, 4 },
00088 { 1, 4, 2, 1, 4 },
00089 { 2, 4, 3, 2, 4 },
00090 { 3, 4, 0, 3, 4 }};
00091 static int Pyramid_R [5][5] = {
00092 { 0, 1, 2, 3, 0 },
00093 { 0, 1, 4, 0, 4 },
00094 { 1, 2, 4, 1, 4 },
00095 { 2, 3, 4, 2, 4 },
00096 { 3, 0, 4, 3, 4 }};
00097 static int Pyramid_RE [5][5] = {
00098 { 0, 3, 2, 1, 0 },
00099 { 0, 1, 4, 0, 4 },
00100 { 1, 2, 4, 1, 4 },
00101 { 2, 3, 4, 2, 4 },
00102 { 3, 0, 4, 3, 4 }};
00103 static int Pyramid_nbN [] = { 4, 3, 3, 3, 3 };
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 static int Penta_F [5][5] = {
00121 { 0, 1, 2, 0, 0 },
00122 { 3, 4, 5, 3, 3 },
00123 { 0, 2, 5, 3, 0 },
00124 { 1, 4, 5, 2, 1 },
00125 { 0, 3, 4, 1, 0 }};
00126 static int Penta_R [5][5] = {
00127 { 0, 1, 2, 0, 0 },
00128 { 3, 4, 5, 3, 3 },
00129 { 0, 3, 5, 2, 0 },
00130 { 1, 2, 5, 4, 1 },
00131 { 0, 1, 4, 3, 0 }};
00132 static int Penta_FE [5][5] = {
00133 { 0, 1, 2, 0, 0 },
00134 { 3, 5, 4, 3, 3 },
00135 { 0, 2, 5, 3, 0 },
00136 { 1, 4, 5, 2, 1 },
00137 { 0, 3, 4, 1, 0 }};
00138 static int Penta_RE [5][5] = {
00139 { 0, 2, 1, 0, 0 },
00140 { 3, 4, 5, 3, 3 },
00141 { 0, 3, 5, 2, 0 },
00142 { 1, 2, 5, 4, 1 },
00143 { 0, 1, 4, 3, 0 }};
00144 static int Penta_nbN [] = { 3, 3, 4, 4, 4 };
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static int Hexa_F [6][5] = {
00162 { 0, 1, 2, 3, 0 },
00163 { 4, 5, 6, 7, 4 },
00164 { 1, 0, 4, 5, 1 },
00165 { 2, 3, 7, 6, 2 },
00166 { 0, 3, 7, 4, 0 },
00167 { 1, 2, 6, 5, 1 }};
00168
00169
00170
00171
00172
00173
00174
00175 static int Hexa_FE [6][5] = {
00176 { 0, 1, 2, 3, 0 } ,
00177 { 4, 7, 6, 5, 4 },
00178 { 0, 4, 5, 1, 0 },
00179 { 3, 2, 6, 7, 3 },
00180 { 0, 3, 7, 4, 0 },
00181 { 1, 5, 6, 2, 1 }};
00182 static int Hexa_RE [6][5] = {
00183 { 0, 3, 2, 1, 0 },
00184 { 4, 5, 6, 7, 4 },
00185 { 0, 1, 5, 4, 0 },
00186 { 3, 7, 6, 2, 3 },
00187 { 0, 4, 7, 3, 0 },
00188 { 1, 2, 6, 5, 1 }};
00189 static int Hexa_nbN [] = { 4, 4, 4, 4, 4, 4 };
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 static int QuadTetra_F [4][7] = {
00207 { 0, 4, 1, 5, 2, 6, 0 },
00208 { 0, 7, 3, 8, 1, 4, 0 },
00209 { 1, 8, 3, 9, 2, 5, 1 },
00210 { 0, 6, 2, 9, 3, 7, 0 }};
00211 static int QuadTetra_R [4][7] = {
00212 { 0, 4, 1, 5, 2, 6, 0 },
00213 { 0, 4, 1, 8, 3, 7, 0 },
00214 { 1, 5, 2, 9, 3, 8, 1 },
00215 { 0, 7, 3, 9, 2, 6, 0 }};
00216 static int QuadTetra_RE [4][7] = {
00217 { 0, 6, 2, 5, 1, 4, 0 },
00218 { 0, 4, 1, 8, 3, 7, 0 },
00219 { 1, 5, 2, 9, 3, 8, 1 },
00220 { 0, 7, 3, 9, 2, 6, 0 }};
00221 static int QuadTetra_nbN [] = { 6, 6, 6, 6 };
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 static int QuadPyram_F [5][9] = {
00245 { 0, 5, 1, 6, 2, 7, 3, 8, 0 },
00246 { 0, 9, 4, 10,1, 5, 0, 4, 4 },
00247 { 1, 10,4, 11,2, 6, 1, 4, 4 },
00248 { 2, 11,4, 12,3, 7, 2, 4, 4 },
00249 { 3, 12,4, 9, 0, 8, 3, 4, 4 }};
00250 static int QuadPyram_R [5][9] = {
00251 { 0, 5, 1, 6, 2, 7, 3, 8, 0 },
00252 { 0, 5, 1, 10,4, 9, 0, 4, 4 },
00253 { 1, 6, 2, 11,4, 10,1, 4, 4 },
00254 { 2, 7, 3, 12,4, 11,2, 4, 4 },
00255 { 3, 8, 0, 9, 4, 12,3, 4, 4 }};
00256 static int QuadPyram_RE [5][9] = {
00257 { 0, 8, 3, 7, 2, 6, 1, 5, 0 },
00258 { 0, 5, 1, 10,4, 9, 0, 4, 4 },
00259 { 1, 6, 2, 11,4, 10,1, 4, 4 },
00260 { 2, 7, 3, 12,4, 11,2, 4, 4 },
00261 { 3, 8, 0, 9, 4, 12,3, 4, 4 }};
00262 static int QuadPyram_nbN [] = { 8, 6, 6, 6, 6 };
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 static int QuadPenta_F [5][9] = {
00290 { 0, 6, 1, 7, 2, 8, 0, 0, 0 },
00291 { 3, 9, 4, 10,5, 11,3, 3, 3 },
00292 { 0, 8, 2, 14,5, 11,3, 12,0 },
00293 { 1, 13,4, 10,5, 14,2, 7, 1 },
00294 { 0, 12,3, 9, 4, 13,1, 6, 0 }};
00295 static int QuadPenta_R [5][9] = {
00296 { 0, 6, 1, 7, 2, 8, 0, 0, 0 },
00297 { 3, 9, 4, 10,5, 11,3, 3, 3 },
00298 { 0, 12,3, 11,5, 14,2, 8, 0 },
00299 { 1, 7, 2, 14,5, 10,4, 13,1 },
00300 { 0, 6, 1, 13,4, 9, 3, 12,0 }};
00301 static int QuadPenta_FE [5][9] = {
00302 { 0, 6, 1, 7, 2, 8, 0, 0, 0 },
00303 { 3,11, 5, 10,4, 9, 3, 3, 3 },
00304 { 0, 8, 2, 14,5, 11,3, 12,0 },
00305 { 1, 13,4, 10,5, 14,2, 7, 1 },
00306 { 0, 12,3, 9, 4, 13,1, 6, 0 }};
00307 static int QuadPenta_RE [5][9] = {
00308 { 0, 8, 2, 7, 1, 6, 0, 0, 0 },
00309 { 3, 9, 4, 10,5, 11,3, 3, 3 },
00310 { 0, 12,3, 11,5, 14,2, 8, 0 },
00311 { 1, 7, 2, 14,5, 10,4, 13,1 },
00312 { 0, 6, 1, 13,4, 9, 3, 12,0 }};
00313 static int QuadPenta_nbN [] = { 6, 6, 8, 8, 8 };
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 static int QuadHexa_F [6][9] = {
00339 { 0, 8, 1, 9, 2, 10,3, 11,0 },
00340 { 4, 12,5, 13,6, 14,7, 15,4 },
00341 { 1, 8, 0, 16,4, 12,5, 17,1 },
00342 { 2, 10,3, 19,7, 14,6, 18,2 },
00343 { 0, 11,3, 19,7, 15,4, 16,0 },
00344 { 1, 9, 2, 18,6, 13,5, 17,1 }};
00345
00346
00347
00348
00349
00350
00351
00352 static int QuadHexa_FE [6][9] = {
00353 { 0, 8, 1, 9, 2, 10,3, 11,0 },
00354 { 4, 15,7, 14,6, 13,5, 12,4 },
00355 { 0, 16,4, 12,5, 17,1, 8, 0 },
00356 { 3, 10,2, 18,6, 14,7, 19,3 },
00357 { 0, 11,3, 19,7, 15,4, 16,0 },
00358 { 1, 17,5, 13,6, 18,2, 9, 1 }};
00359 static int QuadHexa_RE [6][9] = {
00360 { 0, 11,3, 10,2, 9, 1, 8, 0 },
00361 { 4, 12,5, 13,6, 14,7, 15,4 },
00362 { 0, 8, 1, 17,5, 12,4, 16,0 },
00363 { 3, 19,7, 14,6, 18,2, 10,3 },
00364 { 0, 16,4, 15,7, 19,3, 11,0 },
00365 { 1, 9, 2, 18,6, 13,5, 17,1 }};
00366 static int QuadHexa_nbN [] = { 8, 8, 8, 8, 8, 8 };
00367
00368
00369
00370
00371
00372 namespace
00373 {
00374 struct XYZ {
00375 double x;
00376 double y;
00377 double z;
00378 XYZ() { x = 0; y = 0; z = 0; }
00379 XYZ( double X, double Y, double Z ) { x = X; y = Y; z = Z; }
00380 XYZ( const XYZ& other ) { x = other.x; y = other.y; z = other.z; }
00381 XYZ( const SMDS_MeshNode* n ) { x = n->X(); y = n->Y(); z = n->Z(); }
00382 inline XYZ operator-( const XYZ& other );
00383 inline XYZ Crossed( const XYZ& other );
00384 inline double Dot( const XYZ& other );
00385 inline double Magnitude();
00386 };
00387 inline XYZ XYZ::operator-( const XYZ& Right ) {
00388 return XYZ(x - Right.x, y - Right.y, z - Right.z);
00389 }
00390 inline XYZ XYZ::Crossed( const XYZ& Right ) {
00391 return XYZ (y * Right.z - z * Right.y,
00392 z * Right.x - x * Right.z,
00393 x * Right.y - y * Right.x);
00394 }
00395 inline double XYZ::Dot( const XYZ& Other ) {
00396 return(x * Other.x + y * Other.y + z * Other.z);
00397 }
00398 inline double XYZ::Magnitude() {
00399 return sqrt (x * x + y * y + z * z);
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408 SMDS_VolumeTool::SMDS_VolumeTool ()
00409 : myVolume( 0 ),
00410 myPolyedre( 0 ),
00411 myVolForward( true ),
00412 myNbFaces( 0 ),
00413 myVolumeNbNodes( 0 ),
00414 myVolumeNodes( NULL ),
00415 myExternalFaces( false ),
00416 myFaceNbNodes( 0 ),
00417 myCurFace( -1 ),
00418 myFaceNodeIndices( NULL ),
00419 myFaceNodes( NULL )
00420 {
00421
00422 }
00423
00424
00425
00426
00427
00428
00429 SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume)
00430 : myVolume( 0 ),
00431 myPolyedre( 0 ),
00432 myVolForward( true ),
00433 myNbFaces( 0 ),
00434 myVolumeNbNodes( 0 ),
00435 myVolumeNodes( NULL ),
00436 myExternalFaces( false ),
00437 myFaceNbNodes( 0 ),
00438 myCurFace( -1 ),
00439 myFaceNodeIndices( NULL ),
00440 myFaceNodes( NULL )
00441 {
00442
00443 Set( theVolume );
00444 }
00445
00446
00447
00448
00449
00450
00451 SMDS_VolumeTool::~SMDS_VolumeTool()
00452 {
00453 if ( myVolumeNodes != NULL ) delete [] myVolumeNodes;
00454 if ( myFaceNodes != NULL ) delete [] myFaceNodes;
00455
00456 myFaceNodeIndices = NULL;
00457 myVolumeNodes = myFaceNodes = NULL;
00458 }
00459
00460
00461
00462
00463
00464
00465 bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume)
00466 {
00467 myVolume = 0;
00468 myPolyedre = 0;
00469
00470 myVolForward = true;
00471 myNbFaces = 0;
00472 myVolumeNbNodes = 0;
00473 if (myVolumeNodes != NULL) {
00474 delete [] myVolumeNodes;
00475 myVolumeNodes = NULL;
00476 }
00477
00478 myExternalFaces = false;
00479 myFaceNbNodes = 0;
00480
00481 myCurFace = -1;
00482 myFaceNodeIndices = NULL;
00483 if (myFaceNodes != NULL) {
00484 delete [] myFaceNodes;
00485 myFaceNodes = NULL;
00486 }
00487
00488 if ( theVolume && theVolume->GetType() == SMDSAbs_Volume )
00489 {
00490 myVolume = theVolume;
00491
00492 myNbFaces = theVolume->NbFaces();
00493 myVolumeNbNodes = theVolume->NbNodes();
00494
00495
00496 int iNode = 0;
00497 myVolumeNodes = new const SMDS_MeshNode* [myVolumeNbNodes];
00498 SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator();
00499 while ( nodeIt->more() ) {
00500 myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
00501 }
00502
00503 if (myVolume->IsPoly()) {
00504 myPolyedre = dynamic_cast<const SMDS_VtkVolume*>( myVolume );
00505 if (!myPolyedre) {
00506 MESSAGE("Warning: bad volumic element");
00507 return false;
00508 }
00509 }
00510 else {
00511 switch ( myVolumeNbNodes ) {
00512 case 4:
00513 case 5:
00514 case 6:
00515 case 8:
00516 case 10:
00517 case 13:
00518 case 15:
00519 case 20: {
00520
00521 XYZ botNormal;
00522 GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z );
00523 const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ];
00524 int topNodeIndex = myVolume->NbCornerNodes() - 1;
00525 while ( !IsLinked( 0, topNodeIndex, true )) --topNodeIndex;
00526 const SMDS_MeshNode* topNode = myVolumeNodes[ topNodeIndex ];
00527 XYZ upDir (topNode->X() - botNode->X(),
00528 topNode->Y() - botNode->Y(),
00529 topNode->Z() - botNode->Z() );
00530 myVolForward = ( botNormal.Dot( upDir ) < 0 );
00531 break;
00532 }
00533 default:
00534 break;
00535 }
00536 }
00537 }
00538 return ( myVolume != 0 );
00539 }
00540
00541
00542
00543
00544
00545
00546 #define SWAP_NODES(nodes,i1,i2) \
00547 { \
00548 const SMDS_MeshNode* tmp = nodes[ i1 ]; \
00549 nodes[ i1 ] = nodes[ i2 ]; \
00550 nodes[ i2 ] = tmp; \
00551 }
00552 void SMDS_VolumeTool::Inverse ()
00553 {
00554 if ( !myVolume ) return;
00555
00556 if (myVolume->IsPoly()) {
00557 MESSAGE("Warning: attempt to inverse polyhedral volume");
00558 return;
00559 }
00560
00561 myVolForward = !myVolForward;
00562 myCurFace = -1;
00563
00564
00565 switch ( myVolumeNbNodes ) {
00566 case 4:
00567 SWAP_NODES( myVolumeNodes, 1, 2 );
00568 break;
00569 case 5:
00570 SWAP_NODES( myVolumeNodes, 1, 3 );
00571 break;
00572 case 6:
00573 SWAP_NODES( myVolumeNodes, 1, 2 );
00574 SWAP_NODES( myVolumeNodes, 4, 5 );
00575 break;
00576 case 8:
00577 SWAP_NODES( myVolumeNodes, 1, 3 );
00578 SWAP_NODES( myVolumeNodes, 5, 7 );
00579 break;
00580
00581 case 10:
00582 SWAP_NODES( myVolumeNodes, 1, 2 );
00583 SWAP_NODES( myVolumeNodes, 4, 6 );
00584 SWAP_NODES( myVolumeNodes, 8, 9 );
00585 break;
00586 case 13:
00587 SWAP_NODES( myVolumeNodes, 1, 3 );
00588 SWAP_NODES( myVolumeNodes, 5, 8 );
00589 SWAP_NODES( myVolumeNodes, 6, 7 );
00590 SWAP_NODES( myVolumeNodes, 10, 12 );
00591 break;
00592 case 15:
00593 SWAP_NODES( myVolumeNodes, 1, 2 );
00594 SWAP_NODES( myVolumeNodes, 4, 5 );
00595 SWAP_NODES( myVolumeNodes, 6, 8 );
00596 SWAP_NODES( myVolumeNodes, 9, 11 );
00597 SWAP_NODES( myVolumeNodes, 13, 14 );
00598 break;
00599 case 20:
00600 SWAP_NODES( myVolumeNodes, 1, 3 );
00601 SWAP_NODES( myVolumeNodes, 5, 7 );
00602 SWAP_NODES( myVolumeNodes, 8, 11 );
00603 SWAP_NODES( myVolumeNodes, 9, 10 );
00604 SWAP_NODES( myVolumeNodes, 12, 15 );
00605 SWAP_NODES( myVolumeNodes, 13, 14 );
00606 SWAP_NODES( myVolumeNodes, 17, 19 );
00607 break;
00608 default:;
00609 }
00610 }
00611
00612
00613
00614
00615
00616
00617 SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const
00618 {
00619 if ( myPolyedre )
00620 return POLYHEDA;
00621
00622 if ( myVolume ) {
00623
00624
00625
00626
00627
00628
00629
00630
00631 switch(myVolumeNbNodes) {
00632 case 4: return TETRA; break;
00633 case 5: return PYRAM; break;
00634 case 6: return PENTA; break;
00635 case 8: return HEXA; break;
00636 case 10: return QUAD_TETRA; break;
00637 case 13: return QUAD_PYRAM; break;
00638 case 15: return QUAD_PENTA; break;
00639 case 20: return QUAD_HEXA; break;
00640 default: break;
00641 }
00642 }
00643
00644 return UNKNOWN;
00645 }
00646
00647
00648
00649
00650
00651
00652 static double getTetraVolume(const SMDS_MeshNode* n1,
00653 const SMDS_MeshNode* n2,
00654 const SMDS_MeshNode* n3,
00655 const SMDS_MeshNode* n4)
00656 {
00657 double X1 = n1->X();
00658 double Y1 = n1->Y();
00659 double Z1 = n1->Z();
00660
00661 double X2 = n2->X();
00662 double Y2 = n2->Y();
00663 double Z2 = n2->Z();
00664
00665 double X3 = n3->X();
00666 double Y3 = n3->Y();
00667 double Z3 = n3->Z();
00668
00669 double X4 = n4->X();
00670 double Y4 = n4->Y();
00671 double Z4 = n4->Z();
00672
00673 double Q1 = -(X1-X2)*(Y3*Z4-Y4*Z3);
00674 double Q2 = (X1-X3)*(Y2*Z4-Y4*Z2);
00675 double R1 = -(X1-X4)*(Y2*Z3-Y3*Z2);
00676 double R2 = -(X2-X3)*(Y1*Z4-Y4*Z1);
00677 double S1 = (X2-X4)*(Y1*Z3-Y3*Z1);
00678 double S2 = -(X3-X4)*(Y1*Z2-Y2*Z1);
00679
00680 return (Q1+Q2+R1+R2+S1+S2)/6.0;
00681 }
00682
00683
00684
00685
00686
00687
00688 double SMDS_VolumeTool::GetSize() const
00689 {
00690 double V = 0.;
00691 if ( !myVolume )
00692 return 0.;
00693
00694 if ( myVolume->IsPoly() )
00695 {
00696 if ( !myPolyedre )
00697 return 0.;
00698
00699 SMDS_Mesh *mesh = SMDS_Mesh::_meshList[myPolyedre->getMeshId()];
00700
00701
00702 SMDS_VolumeTool* me = const_cast< SMDS_VolumeTool* > ( this );
00703 XYZ baryCenter;
00704 me->GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z);
00705 SMDS_MeshNode *bcNode = mesh->AddNode( baryCenter.x, baryCenter.y, baryCenter.z );
00706
00707 for ( int f = 0; f < NbFaces(); ++f )
00708 {
00709 bool externalFace = me->IsFaceExternal( f );
00710 for ( int n = 2; n < myFaceNbNodes; ++n )
00711 {
00712 double Vn = getTetraVolume( myFaceNodes[ 0 ],
00713 myFaceNodes[ n-1 ],
00714 myFaceNodes[ n ],
00715 bcNode );
00717 V += externalFace ? -Vn : Vn;
00718 }
00719 }
00720 mesh->RemoveNode(bcNode);
00721 }
00722 else
00723 {
00724 const static int ind[] = {
00725 0, 1, 3, 6, 11, 19, 32, 46, 66};
00726 const static int vtab[][4] = {
00727
00728 { 0, 1, 2, 3 },
00729
00730 { 0, 1, 3, 4 },
00731 { 1, 2, 3, 4 },
00732
00733 { 0, 1, 2, 3 },
00734 { 1, 5, 3, 4 },
00735 { 1, 5, 2, 3 },
00736
00737 { 1, 4, 3, 0 },
00738 { 4, 1, 6, 5 },
00739 { 1, 3, 6, 2 },
00740 { 4, 6, 3, 7 },
00741 { 1, 4, 6, 3 },
00742
00743
00744 { 0, 4, 6, 7 },
00745 { 1, 5, 4, 8 },
00746 { 2, 6, 5, 9 },
00747 { 7, 8, 9, 3 },
00748 { 4, 6, 7, 9 },
00749 { 4, 5, 6, 9 },
00750 { 4, 7, 8, 9 },
00751 { 4, 5, 9, 8 },
00752
00753
00754 { 0, 5, 8, 9 },
00755 { 1, 5,10, 6 },
00756 { 2, 6,11, 7 },
00757 { 3, 7,12, 8 },
00758 { 4, 9,11,10 },
00759 { 4, 9,12,11 },
00760 { 10, 5, 9, 8 },
00761 { 10, 8, 9,12 },
00762 { 10, 8,12, 7 },
00763 { 10, 7,12,11 },
00764 { 10, 7,11, 6 },
00765 { 10, 5, 8, 6 },
00766 { 10, 6, 8, 7 },
00767
00768
00769 { 12, 0, 8, 6 },
00770 { 12, 8, 7, 6 },
00771 { 12, 8, 2, 7 },
00772 { 12, 6, 7, 1 },
00773 { 12, 1, 7,13 },
00774 { 12, 7, 2,13 },
00775 { 12, 2,14,13 },
00776
00777 { 12, 3, 9,11 },
00778 { 12,11, 9,10 },
00779 { 12,11,10, 5 },
00780 { 12, 9, 4,10 },
00781 { 12,14, 5,10 },
00782 { 12,14,10, 4 },
00783 { 12,14, 4,13 },
00784
00785
00786 { 16, 0,11, 8 },
00787 { 16,11, 9, 8 },
00788 { 16, 8, 9, 1 },
00789 { 16,11, 3,10 },
00790 { 16,11,10, 9 },
00791 { 16,10, 2, 9 },
00792 { 16, 3,19, 2 },
00793 { 16, 2,19,18 },
00794 { 16, 2,18,17 },
00795 { 16, 2,17, 1 },
00796
00797 { 16, 4,12,15 },
00798 { 16,12, 5,13 },
00799 { 16,12,13,15 },
00800 { 16,13, 6,14 },
00801 { 16,13,14,15 },
00802 { 16,14, 7,15 },
00803 { 16, 6, 5,17 },
00804 { 16,18, 6,17 },
00805 { 16,18, 7, 6 },
00806 { 16,18,19, 7 },
00807
00808 };
00809
00810 int type = GetVolumeType();
00811 int n1 = ind[type];
00812 int n2 = ind[type+1];
00813
00814 for (int i = n1; i < n2; i++) {
00815 V -= getTetraVolume( myVolumeNodes[ vtab[i][0] ],
00816 myVolumeNodes[ vtab[i][1] ],
00817 myVolumeNodes[ vtab[i][2] ],
00818 myVolumeNodes[ vtab[i][3] ]);
00819 }
00820 }
00821 return V;
00822 }
00823
00824
00825
00826
00827
00828
00829 bool SMDS_VolumeTool::GetBaryCenter(double & X, double & Y, double & Z) const
00830 {
00831 X = Y = Z = 0.;
00832 if ( !myVolume )
00833 return false;
00834
00835 for ( int i = 0; i < myVolumeNbNodes; i++ ) {
00836 X += myVolumeNodes[ i ]->X();
00837 Y += myVolumeNodes[ i ]->Y();
00838 Z += myVolumeNodes[ i ]->Z();
00839 }
00840 X /= myVolumeNbNodes;
00841 Y /= myVolumeNbNodes;
00842 Z /= myVolumeNbNodes;
00843
00844 return true;
00845 }
00846
00847
00852
00853
00854 bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol)
00855 {
00856
00857 XYZ p( X,Y,Z );
00858 for ( int iF = 0; iF < myNbFaces; ++iF )
00859 {
00860 XYZ faceNormal;
00861 if ( !GetFaceNormal( iF, faceNormal.x, faceNormal.y, faceNormal.z ))
00862 continue;
00863 if ( !IsFaceExternal( iF ))
00864 faceNormal = XYZ() - faceNormal;
00865
00866 XYZ face2p( p - XYZ( myFaceNodes[0] ));
00867 if ( face2p.Dot( faceNormal ) > tol )
00868 return true;
00869 }
00870 return false;
00871 }
00872
00873
00874
00875
00876
00877
00878 void SMDS_VolumeTool::SetExternalNormal ()
00879 {
00880 myExternalFaces = true;
00881 myCurFace = -1;
00882 }
00883
00884
00885
00886
00887
00888
00889 int SMDS_VolumeTool::NbFaceNodes( int faceIndex )
00890 {
00891 if ( !setFace( faceIndex ))
00892 return 0;
00893 return myFaceNbNodes;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 const SMDS_MeshNode** SMDS_VolumeTool::GetFaceNodes( int faceIndex )
00905 {
00906 if ( !setFace( faceIndex ))
00907 return 0;
00908 return myFaceNodes;
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 const int* SMDS_VolumeTool::GetFaceNodesIndices( int faceIndex )
00920 {
00921 if ( !setFace( faceIndex ))
00922 return 0;
00923
00924 if (myVolume->IsPoly())
00925 {
00926 myPolyIndices.resize( myFaceNbNodes + 1 );
00927 myFaceNodeIndices = & myPolyIndices[0];
00928 for ( int i = 0; i <= myFaceNbNodes; ++i )
00929 myFaceNodeIndices[i] = myVolume->GetNodeIndex( myFaceNodes[i] );
00930 }
00931 return myFaceNodeIndices;
00932 }
00933
00934
00935
00936
00937
00938
00939 bool SMDS_VolumeTool::GetFaceNodes (int faceIndex,
00940 set<const SMDS_MeshNode*>& theFaceNodes )
00941 {
00942 if ( !setFace( faceIndex ))
00943 return false;
00944
00945 theFaceNodes.clear();
00946 int iNode, nbNode = myFaceNbNodes;
00947 for ( iNode = 0; iNode < nbNode; iNode++ )
00948 theFaceNodes.insert( myFaceNodes[ iNode ]);
00949
00950 return true;
00951 }
00952
00953
00954
00955
00956
00957
00958 bool SMDS_VolumeTool::IsFaceExternal( int faceIndex )
00959 {
00960 if ( myExternalFaces || !myVolume )
00961 return true;
00962
00963 if (myVolume->IsPoly()) {
00964 XYZ aNormal, baryCenter, p0 (myPolyedre->GetFaceNode(faceIndex + 1, 1));
00965 GetFaceNormal(faceIndex, aNormal.x, aNormal.y, aNormal.z);
00966 GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z);
00967 XYZ insideVec (baryCenter - p0);
00968 if (insideVec.Dot(aNormal) > 0)
00969 return false;
00970 return true;
00971 }
00972
00973 switch ( myVolumeNbNodes ) {
00974 case 4:
00975 case 5:
00976 case 10:
00977 case 13:
00978
00979 return ( myVolForward || faceIndex != 0 );
00980 case 6:
00981 case 15:
00982
00983 return ( myVolForward ? faceIndex != 1 : faceIndex != 0 );
00984 case 8:
00985 case 20: {
00986
00987 bool odd = faceIndex % 2;
00988 return ( myVolForward ? !odd : odd );
00989 }
00990 default:;
00991 }
00992 return false;
00993 }
00994
00995
00996
00997
00998
00999
01000 bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, double & Z)
01001 {
01002 if ( !setFace( faceIndex ))
01003 return false;
01004
01005 XYZ p1 ( myFaceNodes[0] );
01006 XYZ p2 ( myFaceNodes[1] );
01007 XYZ p3 ( myFaceNodes[2] );
01008 XYZ aVec12( p2 - p1 );
01009 XYZ aVec13( p3 - p1 );
01010 XYZ cross = aVec12.Crossed( aVec13 );
01011
01012
01013 if ( myFaceNbNodes >3 ) {
01014 XYZ p4 ( myFaceNodes[3] );
01015 XYZ aVec14( p4 - p1 );
01016 XYZ cross2 = aVec13.Crossed( aVec14 );
01017 cross.x += cross2.x;
01018 cross.y += cross2.y;
01019 cross.z += cross2.z;
01020 }
01021
01022 double size = cross.Magnitude();
01023 if ( size <= DBL_MIN )
01024 return false;
01025
01026 X = cross.x / size;
01027 Y = cross.y / size;
01028 Z = cross.z / size;
01029
01030 return true;
01031 }
01032
01033
01037
01038
01039 bool SMDS_VolumeTool::GetFaceBaryCenter (int faceIndex, double & X, double & Y, double & Z)
01040 {
01041 if ( !setFace( faceIndex ))
01042 return false;
01043
01044 X = Y = Z = 0.0;
01045 for ( int i = 0; i < myFaceNbNodes; ++i )
01046 {
01047 X += myFaceNodes[i]->X() / myFaceNbNodes;
01048 Y += myFaceNodes[i]->Y() / myFaceNbNodes;
01049 Z += myFaceNodes[i]->Z() / myFaceNbNodes;
01050 }
01051 return true;
01052 }
01053
01054
01055
01056
01057
01058
01059 double SMDS_VolumeTool::GetFaceArea( int faceIndex )
01060 {
01061 if (myVolume->IsPoly()) {
01062 MESSAGE("Warning: attempt to obtain area of a face of polyhedral volume");
01063 return 0;
01064 }
01065
01066 if ( !setFace( faceIndex ))
01067 return 0;
01068
01069 XYZ p1 ( myFaceNodes[0] );
01070 XYZ p2 ( myFaceNodes[1] );
01071 XYZ p3 ( myFaceNodes[2] );
01072 XYZ aVec12( p2 - p1 );
01073 XYZ aVec13( p3 - p1 );
01074 double area = aVec12.Crossed( aVec13 ).Magnitude() * 0.5;
01075
01076 if ( myFaceNbNodes == 4 ) {
01077 XYZ p4 ( myFaceNodes[3] );
01078 XYZ aVec14( p4 - p1 );
01079 area += aVec14.Crossed( aVec13 ).Magnitude() * 0.5;
01080 }
01081 return area;
01082 }
01083
01084
01085
01086
01087
01088
01089 int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const
01090 {
01091 int ind = -1;
01092 if (myVolume->IsPoly()) {
01093 MESSAGE("Warning: attempt to obtain opposite face on polyhedral volume");
01094 return ind;
01095 }
01096
01097 if ( faceIndex >= 0 && faceIndex < NbFaces() ) {
01098 switch ( myVolumeNbNodes ) {
01099 case 6:
01100 if ( faceIndex == 0 || faceIndex == 1 )
01101 ind = 1 - faceIndex;
01102 break;
01103 case 8:
01104 ind = faceIndex + ( faceIndex % 2 ? -1 : 1 );
01105 break;
01106 default:;
01107 }
01108 }
01109 return ind;
01110 }
01111
01112
01113
01114
01115
01116
01117
01118 bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1,
01119 const SMDS_MeshNode* theNode2,
01120 const bool theIgnoreMediumNodes) const
01121 {
01122 if ( !myVolume )
01123 return false;
01124
01125 if (myVolume->IsPoly()) {
01126 if (!myPolyedre) {
01127 MESSAGE("Warning: bad volumic element");
01128 return false;
01129 }
01130 bool isLinked = false;
01131 int iface;
01132 for (iface = 1; iface <= myNbFaces && !isLinked; iface++) {
01133 int inode, nbFaceNodes = myPolyedre->NbFaceNodes(iface);
01134
01135 for (inode = 1; inode <= nbFaceNodes && !isLinked; inode++) {
01136 const SMDS_MeshNode* curNode = myPolyedre->GetFaceNode(iface, inode);
01137
01138 if (curNode == theNode1 || curNode == theNode2) {
01139 int inextnode = (inode == nbFaceNodes) ? 1 : inode + 1;
01140 const SMDS_MeshNode* nextNode = myPolyedre->GetFaceNode(iface, inextnode);
01141
01142 if ((curNode == theNode1 && nextNode == theNode2) ||
01143 (curNode == theNode2 && nextNode == theNode1)) {
01144 isLinked = true;
01145 }
01146 }
01147 }
01148 }
01149 return isLinked;
01150 }
01151
01152
01153 int i1 = -1, i2 = -1;
01154 for ( int i = 0; i < myVolumeNbNodes; i++ ) {
01155 if ( myVolumeNodes[ i ] == theNode1 )
01156 i1 = i;
01157 else if ( myVolumeNodes[ i ] == theNode2 )
01158 i2 = i;
01159 }
01160 return IsLinked( i1, i2 );
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170 bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
01171 const int theNode2Index,
01172 bool theIgnoreMediumNodes) const
01173 {
01174 if ( myVolume->IsPoly() ) {
01175 return IsLinked(myVolumeNodes[theNode1Index], myVolumeNodes[theNode2Index]);
01176 }
01177
01178 int minInd = min( theNode1Index, theNode2Index );
01179 int maxInd = max( theNode1Index, theNode2Index );
01180
01181 if ( minInd < 0 || maxInd > myVolumeNbNodes - 1 || maxInd == minInd )
01182 return false;
01183
01184 SMDSAbs_EntityType type = myVolume->GetEntityType();
01185 if ( myVolume->IsQuadratic() )
01186 {
01187 int firstMediumInd = myVolume->NbCornerNodes();
01188 if ( minInd >= firstMediumInd )
01189 return false;
01190 if ( maxInd < firstMediumInd )
01191 {
01192 if ( theIgnoreMediumNodes )
01193 type = SMDSAbs_EntityType( int(type)-1 );
01194 else
01195 return false;
01196 }
01197 }
01198
01199 switch ( type ) {
01200 case SMDSEntity_Tetra:
01201 return true;
01202 case SMDSEntity_Hexa:
01203 switch ( maxInd - minInd ) {
01204 case 1: return minInd != 3;
01205 case 3: return minInd == 0 || minInd == 4;
01206 case 4: return true;
01207 default:;
01208 }
01209 break;
01210 case SMDSEntity_Pyramid:
01211 if ( maxInd == 4 )
01212 return true;
01213 switch ( maxInd - minInd ) {
01214 case 1:
01215 case 3: return true;
01216 default:;
01217 }
01218 break;
01219 case SMDSEntity_Penta:
01220 switch ( maxInd - minInd ) {
01221 case 1: return minInd != 2;
01222 case 2: return minInd == 0 || minInd == 3;
01223 case 3: return true;
01224 default:;
01225 }
01226 break;
01227 case SMDSEntity_Quad_Tetra:
01228 {
01229 switch ( minInd ) {
01230 case 0: if( maxInd==4 || maxInd==6 || maxInd==7 ) return true;
01231 case 1: if( maxInd==4 || maxInd==5 || maxInd==8 ) return true;
01232 case 2: if( maxInd==5 || maxInd==6 || maxInd==9 ) return true;
01233 case 3: if( maxInd==7 || maxInd==8 || maxInd==9 ) return true;
01234 default:;
01235 }
01236 break;
01237 }
01238 case SMDSEntity_Quad_Hexa:
01239 {
01240 switch ( minInd ) {
01241 case 0: if( maxInd==8 || maxInd==11 || maxInd==16 ) return true;
01242 case 1: if( maxInd==8 || maxInd==9 || maxInd==17 ) return true;
01243 case 2: if( maxInd==9 || maxInd==10 || maxInd==18 ) return true;
01244 case 3: if( maxInd==10 || maxInd==11 || maxInd==19 ) return true;
01245 case 4: if( maxInd==12 || maxInd==15 || maxInd==16 ) return true;
01246 case 5: if( maxInd==12 || maxInd==13 || maxInd==17 ) return true;
01247 case 6: if( maxInd==13 || maxInd==14 || maxInd==18 ) return true;
01248 case 7: if( maxInd==14 || maxInd==15 || maxInd==19 ) return true;
01249 default:;
01250 }
01251 break;
01252 }
01253 case SMDSEntity_Quad_Pyramid:
01254 {
01255 switch ( minInd ) {
01256 case 0: if( maxInd==5 || maxInd==8 || maxInd==9 ) return true;
01257 case 1: if( maxInd==5 || maxInd==6 || maxInd==10 ) return true;
01258 case 2: if( maxInd==6 || maxInd==7 || maxInd==11 ) return true;
01259 case 3: if( maxInd==7 || maxInd==8 || maxInd==12 ) return true;
01260 case 4: if( maxInd==9 || maxInd==10 || maxInd==11 || maxInd==12 ) return true;
01261 default:;
01262 }
01263 break;
01264 }
01265 case SMDSEntity_Quad_Penta:
01266 {
01267 switch ( minInd ) {
01268 case 0: if( maxInd==6 || maxInd==8 || maxInd==12 ) return true;
01269 case 1: if( maxInd==6 || maxInd==7 || maxInd==13 ) return true;
01270 case 2: if( maxInd==7 || maxInd==8 || maxInd==14 ) return true;
01271 case 3: if( maxInd==9 || maxInd==11 || maxInd==12 ) return true;
01272 case 4: if( maxInd==9 || maxInd==10 || maxInd==13 ) return true;
01273 case 5: if( maxInd==10 || maxInd==11 || maxInd==14 ) return true;
01274 default:;
01275 }
01276 break;
01277 }
01278 default:;
01279 }
01280 return false;
01281 }
01282
01283
01284
01285
01286
01287
01288 int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
01289 {
01290 if ( myVolume ) {
01291 for ( int i = 0; i < myVolumeNbNodes; i++ ) {
01292 if ( myVolumeNodes[ i ] == theNode )
01293 return i;
01294 }
01295 }
01296 return -1;
01297 }
01298
01299
01305
01306
01307 int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces)
01308 {
01309 faces.clear();
01310 faces.reserve( NbFaces() );
01311 for ( int iF = 0; iF < NbFaces(); ++iF ) {
01312 const SMDS_MeshFace* face = 0;
01313 const SMDS_MeshNode** nodes = GetFaceNodes( iF );
01314 switch ( NbFaceNodes( iF )) {
01315 case 3:
01316 face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2] ); break;
01317 case 4:
01318 face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
01319 case 6:
01320 face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2],
01321 nodes[3], nodes[4], nodes[5]); break;
01322 case 8:
01323 face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3],
01324 nodes[4], nodes[5], nodes[6], nodes[7]); break;
01325 }
01326 if ( face )
01327 faces.push_back( face );
01328 }
01329 return faces.size();
01330 }
01331
01332
01333
01339
01340
01341 int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges) const
01342 {
01343 edges.clear();
01344 edges.reserve( myVolumeNbNodes * 2 );
01345 for ( int i = 0; i < myVolumeNbNodes; ++i ) {
01346 for ( int j = i + 1; j < myVolumeNbNodes; ++j ) {
01347 if ( IsLinked( i, j )) {
01348 const SMDS_MeshElement* edge =
01349 SMDS_Mesh::FindEdge( myVolumeNodes[i], myVolumeNodes[j] );
01350 if ( edge )
01351 edges.push_back( edge );
01352 }
01353 }
01354 }
01355 return edges.size();
01356 }
01357
01358
01364
01365
01366 bool SMDS_VolumeTool::IsFreeFace( int faceIndex, const SMDS_MeshElement** otherVol )
01367 {
01368 const bool isFree = true;
01369
01370 if (!setFace( faceIndex ))
01371 return !isFree;
01372
01373 const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex );
01374 const int nbFaceNodes = myFaceNbNodes;
01375
01376
01377 int maxNbShared = -1;
01378 typedef map< const SMDS_MeshElement*, int > TElemIntMap;
01379 TElemIntMap volNbShared;
01380 TElemIntMap::iterator vNbIt;
01381 for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
01382 const SMDS_MeshNode* n = nodes[ iNode ];
01383 SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
01384 while ( eIt->more() ) {
01385 const SMDS_MeshElement* elem = eIt->next();
01386 if ( elem != myVolume ) {
01387 vNbIt = volNbShared.insert( make_pair( elem, 0 )).first;
01388 (*vNbIt).second++;
01389 if ( vNbIt->second > maxNbShared )
01390 maxNbShared = vNbIt->second;
01391 }
01392 }
01393 }
01394 if ( maxNbShared < 3 )
01395 return isFree;
01396
01397
01398
01399 XYZ intNormal;
01400 GetFaceNormal( faceIndex, intNormal.x, intNormal.y, intNormal.z );
01401 if ( IsFaceExternal( faceIndex ))
01402 intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z );
01403 XYZ p0 ( nodes[0] ), baryCenter;
01404 for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); ) {
01405 const int& nbShared = (*vNbIt).second;
01406 if ( nbShared >= 3 ) {
01407 SMDS_VolumeTool volume( (*vNbIt).first );
01408 volume.GetBaryCenter( baryCenter.x, baryCenter.y, baryCenter.z );
01409 XYZ intNormal2( baryCenter - p0 );
01410 if ( intNormal.Dot( intNormal2 ) < 0 ) {
01411
01412 if ( nbShared >= nbFaceNodes )
01413 {
01414
01415 if ( otherVol ) *otherVol = vNbIt->first;
01416 return !isFree;
01417 }
01418 ++vNbIt;
01419 continue;
01420 }
01421 }
01422
01423 volNbShared.erase( vNbIt++ );
01424 }
01425
01426
01427
01428 if ( volNbShared.size() < 2 ) {
01429 return isFree;
01430 }
01431
01432
01433 for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
01434 {
01435 const SMDS_MeshNode* n = nodes[ iNode ];
01436
01437 bool isShared = false;
01438 SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator( SMDSAbs_Volume );
01439 while ( eIt->more() && !isShared )
01440 isShared = volNbShared.count( eIt->next() );
01441 if ( !isShared )
01442 return isFree;
01443 }
01444 if ( otherVol ) *otherVol = volNbShared.begin()->first;
01445 return !isFree;
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 }
01480
01481
01482
01483
01484
01485
01486 int SMDS_VolumeTool::GetFaceIndex( const set<const SMDS_MeshNode*>& theFaceNodes )
01487 {
01488 for ( int iFace = 0; iFace < myNbFaces; iFace++ ) {
01489 const SMDS_MeshNode** nodes = GetFaceNodes( iFace );
01490 int nbFaceNodes = NbFaceNodes( iFace );
01491 set<const SMDS_MeshNode*> nodeSet;
01492 for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
01493 nodeSet.insert( nodes[ iNode ] );
01494 if ( theFaceNodes == nodeSet )
01495 return iFace;
01496 }
01497 return -1;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 bool SMDS_VolumeTool::setFace( int faceIndex )
01525 {
01526 if ( !myVolume )
01527 return false;
01528
01529 if ( myCurFace == faceIndex )
01530 return true;
01531
01532 myCurFace = -1;
01533
01534 if ( faceIndex < 0 || faceIndex >= NbFaces() )
01535 return false;
01536
01537 if (myFaceNodes != NULL) {
01538 delete [] myFaceNodes;
01539 myFaceNodes = NULL;
01540 }
01541
01542 if (myVolume->IsPoly()) {
01543 if (!myPolyedre) {
01544 MESSAGE("Warning: bad volumic element");
01545 return false;
01546 }
01547
01548
01549 bool isGoodOri = true;
01550 if (myExternalFaces)
01551 isGoodOri = IsFaceExternal( faceIndex );
01552
01553
01554 int iNode;
01555 myFaceNbNodes = myPolyedre->NbFaceNodes(faceIndex + 1);
01556 myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
01557 if (isGoodOri) {
01558 for ( iNode = 0; iNode < myFaceNbNodes; iNode++ )
01559 myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, iNode + 1);
01560 } else {
01561 for ( iNode = 0; iNode < myFaceNbNodes; iNode++ )
01562 myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, myFaceNbNodes - iNode);
01563 }
01564 myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ];
01565
01566 }
01567 else {
01568
01569 switch ( myVolumeNbNodes ) {
01570 case 4:
01571 myFaceNbNodes = Tetra_nbN[ faceIndex ];
01572 if ( myExternalFaces )
01573 myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_RE[ faceIndex ];
01574 else
01575 myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_R[ faceIndex ];
01576 break;
01577 case 5:
01578 myFaceNbNodes = Pyramid_nbN[ faceIndex ];
01579 if ( myExternalFaces )
01580 myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_RE[ faceIndex ];
01581 else
01582 myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_R[ faceIndex ];
01583 break;
01584 case 6:
01585 myFaceNbNodes = Penta_nbN[ faceIndex ];
01586 if ( myExternalFaces )
01587 myFaceNodeIndices = myVolForward ? Penta_FE[ faceIndex ] : Penta_RE[ faceIndex ];
01588 else
01589 myFaceNodeIndices = myVolForward ? Penta_F[ faceIndex ] : Penta_R[ faceIndex ];
01590 break;
01591 case 8:
01592 myFaceNbNodes = Hexa_nbN[ faceIndex ];
01593 if ( myExternalFaces )
01594 myFaceNodeIndices = myVolForward ? Hexa_FE[ faceIndex ] : Hexa_RE[ faceIndex ];
01595 else
01596 myFaceNodeIndices = Hexa_F[ faceIndex ];
01597 break;
01598 case 10:
01599 myFaceNbNodes = QuadTetra_nbN[ faceIndex ];
01600 if ( myExternalFaces )
01601 myFaceNodeIndices = myVolForward ? QuadTetra_F[ faceIndex ] : QuadTetra_RE[ faceIndex ];
01602 else
01603 myFaceNodeIndices = myVolForward ? QuadTetra_F[ faceIndex ] : QuadTetra_R[ faceIndex ];
01604 break;
01605 case 13:
01606 myFaceNbNodes = QuadPyram_nbN[ faceIndex ];
01607 if ( myExternalFaces )
01608 myFaceNodeIndices = myVolForward ? QuadPyram_F[ faceIndex ] : QuadPyram_RE[ faceIndex ];
01609 else
01610 myFaceNodeIndices = myVolForward ? QuadPyram_F[ faceIndex ] : QuadPyram_R[ faceIndex ];
01611 break;
01612 case 15:
01613 myFaceNbNodes = QuadPenta_nbN[ faceIndex ];
01614 if ( myExternalFaces )
01615 myFaceNodeIndices = myVolForward ? QuadPenta_FE[ faceIndex ] : QuadPenta_RE[ faceIndex ];
01616 else
01617 myFaceNodeIndices = myVolForward ? QuadPenta_F[ faceIndex ] : QuadPenta_R[ faceIndex ];
01618 break;
01619 case 20:
01620 myFaceNbNodes = QuadHexa_nbN[ faceIndex ];
01621 if ( myExternalFaces )
01622 myFaceNodeIndices = myVolForward ? QuadHexa_FE[ faceIndex ] : QuadHexa_RE[ faceIndex ];
01623 else
01624 myFaceNodeIndices = QuadHexa_F[ faceIndex ];
01625 break;
01626 default:
01627 return false;
01628 }
01629
01630
01631 myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1];
01632 for ( int iNode = 0; iNode < myFaceNbNodes; iNode++ )
01633 myFaceNodes[ iNode ] = myVolumeNodes[ myFaceNodeIndices[ iNode ]];
01634 myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ];
01635 }
01636
01637 myCurFace = faceIndex;
01638
01639 return true;
01640 }
01641
01642
01643
01644
01645
01646
01647 SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetType(int nbNodes)
01648 {
01649 switch ( nbNodes ) {
01650 case 4: return TETRA;
01651 case 5: return PYRAM;
01652 case 6: return PENTA;
01653 case 8: return HEXA;
01654 case 10: return QUAD_TETRA;
01655 case 13: return QUAD_PYRAM;
01656 case 15: return QUAD_PENTA;
01657 case 20: return QUAD_HEXA;
01658 default:return UNKNOWN;
01659 }
01660 }
01661
01662
01663
01664
01665
01666
01667 int SMDS_VolumeTool::NbFaces( VolumeType type )
01668 {
01669 switch ( type ) {
01670 case TETRA :
01671 case QUAD_TETRA: return 4;
01672 case PYRAM :
01673 case QUAD_PYRAM: return 5;
01674 case PENTA :
01675 case QUAD_PENTA: return 5;
01676 case HEXA :
01677 case QUAD_HEXA : return 6;
01678 default: return 0;
01679 }
01680 }
01681
01682
01688
01689
01690 int SMDS_VolumeTool::NbCornerNodes(VolumeType type)
01691 {
01692 switch ( type ) {
01693 case TETRA :
01694 case QUAD_TETRA: return 4;
01695 case PYRAM :
01696 case QUAD_PYRAM: return 5;
01697 case PENTA :
01698 case QUAD_PENTA: return 6;
01699 case HEXA :
01700 case QUAD_HEXA : return 8;
01701 default: return 0;
01702 }
01703 return 0;
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 const int* SMDS_VolumeTool::GetFaceNodesIndices(VolumeType type,
01716 int faceIndex,
01717 bool external)
01718 {
01719 switch ( type ) {
01720 case TETRA: return Tetra_F[ faceIndex ];
01721 case PYRAM: return Pyramid_F[ faceIndex ];
01722 case PENTA: return external ? Penta_FE[ faceIndex ] : Penta_F[ faceIndex ];
01723 case HEXA: return external ? Hexa_FE[ faceIndex ] : Hexa_F[ faceIndex ];
01724 case QUAD_TETRA: return QuadTetra_F[ faceIndex ];
01725 case QUAD_PYRAM: return QuadPyram_F[ faceIndex ];
01726 case QUAD_PENTA: return external ? QuadPenta_FE[ faceIndex ] : QuadPenta_F[ faceIndex ];
01727 case QUAD_HEXA: return external ? QuadHexa_FE[ faceIndex ] : QuadHexa_F[ faceIndex ];
01728 default:;
01729 }
01730 return 0;
01731 }
01732
01733
01734
01735
01736
01737
01738 int SMDS_VolumeTool::NbFaceNodes(VolumeType type,
01739 int faceIndex )
01740 {
01741 switch ( type ) {
01742 case TETRA: return Tetra_nbN[ faceIndex ];
01743 case PYRAM: return Pyramid_nbN[ faceIndex ];
01744 case PENTA: return Penta_nbN[ faceIndex ];
01745 case HEXA: return Hexa_nbN[ faceIndex ];
01746 case QUAD_TETRA: return QuadTetra_nbN[ faceIndex ];
01747 case QUAD_PYRAM: return QuadPyram_nbN[ faceIndex ];
01748 case QUAD_PENTA: return QuadPenta_nbN[ faceIndex ];
01749 case QUAD_HEXA: return QuadHexa_nbN[ faceIndex ];
01750 default:;
01751 }
01752 return 0;
01753 }
01754
01755
01756
01757
01758
01759
01760 const SMDS_MeshVolume* SMDS_VolumeTool::Element() const
01761 {
01762 return static_cast<const SMDS_MeshVolume*>( myVolume );
01763 }
01764
01765
01766
01767
01768
01769
01770 int SMDS_VolumeTool::ID() const
01771 {
01772 return myVolume ? myVolume->GetID() : 0;
01773 }