Version: 6.3.1

src/SMDS/SMDS_VolumeTool.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File      : SMDS_VolumeTool.cxx
00024 // Created   : Tue Jul 13 12:22:13 2004
00025 // Author    : Edward AGAPOV (eap)
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 // Node indices in faces depending on volume orientation
00048 // making most faces normals external
00049 // ======================================================
00050 
00051 /*
00052 //           N3
00053 //           +
00054 //          /|\
00055 //         / | \
00056 //        /  |  \
00057 //    N0 +---|---+ N1                TETRAHEDRON
00058 //       \   |   /
00059 //        \  |  /
00060 //         \ | /
00061 //          \|/
00062 //           +
00063 //           N2
00064 */
00065 static int Tetra_F [4][4] = { // FORWARD == EXTERNAL
00066   { 0, 1, 2, 0 },              // All faces have external normals
00067   { 0, 3, 1, 0 },
00068   { 1, 3, 2, 1 },
00069   { 0, 2, 3, 0 }}; 
00070 static int Tetra_R [4][4] = { // REVERSED
00071   { 0, 1, 2, 0 },             // All faces but a bottom have external normals
00072   { 0, 1, 3, 0 },
00073   { 1, 2, 3, 1 },
00074   { 0, 3, 2, 0 }};
00075 static int Tetra_RE [4][4] = { // REVERSED -> FORWARD (EXTERNAL)
00076   { 0, 2, 1, 0 },              // All faces have external normals
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 //     PYRAMID
00084 //
00085 static int Pyramid_F [5][5] = { // FORWARD == EXTERNAL
00086   { 0, 1, 2, 3, 0 },            // All faces have external normals
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] = { // REVERSED
00092   { 0, 1, 2, 3, 0 },            // All faces but a bottom have external normals
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] = { // REVERSED -> FORWARD (EXTERNAL)
00098   { 0, 3, 2, 1, 0 },             // All faces but a bottom have external normals
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 //            + N4
00107 //           /|\
00108 //          / | \
00109 //         /  |  \
00110 //        /   |   \
00111 //    N3 +---------+ N5
00112 //       |    |    |
00113 //       |    + N1 |
00114 //       |   / \   |                PENTAHEDRON
00115 //       |  /   \  |
00116 //       | /     \ |
00117 //       |/       \|
00118 //    N0 +---------+ N2
00119 */
00120 static int Penta_F [5][5] = { // FORWARD
00121   { 0, 1, 2, 0, 0 },          // Top face has an internal normal, other - external
00122   { 3, 4, 5, 3, 3 },          // 0 is bottom, 1 is top face
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] = { // REVERSED
00127   { 0, 1, 2, 0, 0 },          // Bottom face has an internal normal, other - external
00128   { 3, 4, 5, 3, 3 },          // 0 is bottom, 1 is top face
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] = { // FORWARD -> EXTERNAL
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] = { // REVERSED -> EXTERNAL
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 //         N5+----------+N6
00148 //          /|         /|
00149 //         / |        / |
00150 //        /  |       /  |
00151 //     N4+----------+N7 |
00152 //       |   |      |   |           HEXAHEDRON
00153 //       |   |      |   |
00154 //       |   |      |   |
00155 //       | N1+------|---+N2
00156 //       |  /       |  /
00157 //       | /        | /
00158 //       |/         |/
00159 //     N0+----------+N3
00160 */
00161 static int Hexa_F [6][5] = { // FORWARD
00162   { 0, 1, 2, 3, 0 },         // opposite faces are neighbouring,
00163   { 4, 5, 6, 7, 4 },         // odd face(1,3,5) normal is internal, even(0,2,4) - external
00164   { 1, 0, 4, 5, 1 },         // same index nodes of opposite faces are linked
00165   { 2, 3, 7, 6, 2 }, 
00166   { 0, 3, 7, 4, 0 }, 
00167   { 1, 2, 6, 5, 1 }};
00168 // static int Hexa_R [6][5] = { // REVERSED
00169 //   { 0, 3, 2, 1, 0 },         // opposite faces are neighbouring,
00170 //   { 4, 7, 6, 5, 4 },         // odd face(1,3,5) normal is external, even(0,2,4) - internal
00171 //   { 1, 5, 4, 0, 1 },         // same index nodes of opposite faces are linked
00172 //   { 2, 6, 7, 3, 2 }, 
00173 //   { 0, 4, 7, 3, 0 }, 
00174 //   { 1, 5, 6, 2, 1 }};
00175 static int Hexa_FE [6][5] = { // FORWARD -> EXTERNAL
00176   { 0, 1, 2, 3, 0 } ,         // opposite faces are neighbouring,
00177   { 4, 7, 6, 5, 4 },          // all face normals are external,
00178   { 0, 4, 5, 1, 0 },          // links in opposite faces: 0-0, 1-3, 2-2, 3-1
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] = { // REVERSED -> EXTERNAL
00183   { 0, 3, 2, 1, 0 },          // opposite faces are neighbouring,
00184   { 4, 5, 6, 7, 4 },          // all face normals are external,
00185   { 0, 1, 5, 4, 0 },          // links in opposite faces: 0-0, 1-3, 2-2, 3-1
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 //           N3
00194 //           +
00195 //          /|\
00196 //        7/ | \8
00197 //        /  |4 \                    QUADRATIC
00198 //    N0 +---|---+ N1                TETRAHEDRON
00199 //       \   +9  /
00200 //        \  |  /
00201 //        6\ | /5
00202 //          \|/
00203 //           +
00204 //           N2
00205 */
00206 static int QuadTetra_F [4][7] = { // FORWARD == EXTERNAL
00207   { 0, 4, 1, 5, 2, 6, 0 },        // All faces have external normals
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] = { // REVERSED
00212   { 0, 4, 1, 5, 2, 6, 0 },        // All faces but a bottom have external normals
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] = { // REVERSED -> FORWARD (EXTERNAL)
00217   { 0, 6, 2, 5, 1, 4, 0 },              // All faces have external normals
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 //     QUADRATIC
00225 //     PYRAMID
00226 //
00227 //            +4
00228 //
00229 //            
00230 //       10+-----+11
00231 //         |     |        9 - middle point for (0,4) etc.
00232 //         |     |
00233 //        9+-----+12
00234 //
00235 //            6
00236 //      1+----+----+2
00237 //       |         |
00238 //       |         |
00239 //      5+         +7
00240 //       |         |
00241 //       |         |
00242 //      0+----+----+3
00243 //            8
00244 static int QuadPyram_F [5][9] = {  // FORWARD == EXTERNAL
00245   { 0, 5, 1, 6, 2, 7, 3, 8, 0 },   // All faces have external normals
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] = {  // REVERSED
00251   { 0, 5, 1, 6, 2, 7, 3, 8, 0 },   // All faces but a bottom have external normals
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] = { // REVERSED -> FORWARD (EXTERNAL)
00257   { 0, 8, 3, 7, 2, 6, 1, 5, 0 },   // All faces but a bottom have external normals
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 //            + N4
00266 //           /|\
00267 //         9/ | \10
00268 //         /  |  \
00269 //        /   |   \
00270 //    N3 +----+----+ N5
00271 //       |    |11  |
00272 //       |    |    |
00273 //       |    +13  |                QUADRATIC
00274 //       |    |    |                PENTAHEDRON
00275 //       |    |    |
00276 //       |    |    |
00277 //       |    |    |
00278 //     12+    |    +14
00279 //       |    |    |
00280 //       |    |    |
00281 //       |    + N1 |
00282 //       |   / \   |               
00283 //       | 6/   \7 |
00284 //       | /     \ |
00285 //       |/       \|
00286 //    N0 +---------+ N2
00287 //            8
00288 */
00289 static int QuadPenta_F [5][9] = {  // FORWARD
00290   { 0, 6, 1, 7, 2, 8, 0, 0, 0 },   // Top face has an internal normal, other - external
00291   { 3, 9, 4, 10,5, 11,3, 3, 3 },   // 0 is bottom, 1 is top face
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] = { // REVERSED
00296   { 0, 6, 1, 7, 2, 8, 0, 0, 0 },  // Bottom face has an internal normal, other - external
00297   { 3, 9, 4, 10,5, 11,3, 3, 3 },  // 0 is bottom, 1 is top face
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] = { // FORWARD -> EXTERNAL
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] = { // REVERSED -> EXTERNAL
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 //                 13
00317 //         N5+-----+-----+N6
00318 //          /|          /|
00319 //       12+ |       14+ |
00320 //        /  |        /  |
00321 //     N4+-----+-----+N7 |           QUADRATIC
00322 //       |   | 15    |   |           HEXAHEDRON
00323 //       |   |       |   |
00324 //       | 17+       |   +18
00325 //       |   |       |   |
00326 //       |   |       |   |
00327 //       |   |       |   |
00328 //     16+   |       +19 |
00329 //       |   |       |   |
00330 //       |   |     9 |   |
00331 //       | N1+-----+-|---+N2
00332 //       |  /        |  /
00333 //       | +8        | +10
00334 //       |/          |/
00335 //     N0+-----+-----+N3
00336 //             11
00337 */
00338 static int QuadHexa_F [6][9] = {  // FORWARD
00339   { 0, 8, 1, 9, 2, 10,3, 11,0 },  // opposite faces are neighbouring,
00340   { 4, 12,5, 13,6, 14,7, 15,4 },  // odd face(1,3,5) normal is internal, even(0,2,4) - external
00341   { 1, 8, 0, 16,4, 12,5, 17,1 },  // same index nodes of opposite faces are linked
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 // static int Hexa_R [6][5] = { // REVERSED
00346 //   { 0, 3, 2, 1, 0 },         // opposite faces are neighbouring,
00347 //   { 4, 7, 6, 5, 4 },         // odd face(1,3,5) normal is external, even(0,2,4) - internal
00348 //   { 1, 5, 4, 0, 1 },         // same index nodes of opposite faces are linked
00349 //   { 2, 6, 7, 3, 2 }, 
00350 //   { 0, 4, 7, 3, 0 }, 
00351 //   { 1, 5, 6, 2, 1 }};
00352 static int QuadHexa_FE [6][9] = {  // FORWARD -> EXTERNAL
00353   { 0, 8, 1, 9, 2, 10,3, 11,0 },   // opposite faces are neighbouring,
00354   { 4, 15,7, 14,6, 13,5, 12,4 },   // all face normals are external,
00355   { 0, 16,4, 12,5, 17,1, 8, 0 },   // links in opposite faces: 0-0, 1-3, 2-2, 3-1
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] = {  // REVERSED -> EXTERNAL
00360   { 0, 11,3, 10,2, 9, 1, 8, 0 },   // opposite faces are neighbouring,
00361   { 4, 12,5, 13,6, 14,7, 15,4 },   // all face normals are external,
00362   { 0, 8, 1, 17,5, 12,4, 16,0 },   // links in opposite faces: 0-0, 1-3, 2-2, 3-1
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 // to perform some calculations without linkage to CASCADE
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 //function : SMDS_VolumeTool
00405 //purpose  : 
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   //MESSAGE("******************************************************** SMDS_VolumeToo");
00422 }
00423 
00424 //=======================================================================
00425 //function : SMDS_VolumeTool
00426 //purpose  : 
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   //MESSAGE("******************************************************** SMDS_VolumeToo");
00443   Set( theVolume );
00444 }
00445 
00446 //=======================================================================
00447 //function : SMDS_VolumeTool
00448 //purpose  : 
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 //function : SetVolume
00462 //purpose  : Set volume to iterate on
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     // set volume nodes
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         // define volume orientation
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, /*ignoreMediumNodes=*/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 //function : Inverse
00543 //purpose  : Inverse volume
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   // inverse top and bottom faces
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 //function : GetVolumeType
00614 //purpose  : 
00615 //=======================================================================
00616 
00617 SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const
00618 {
00619   if ( myPolyedre )
00620     return POLYHEDA;
00621 
00622   if ( myVolume ) {
00623 //    static const VolumeType types[] = {
00624 //      TETRA,     // myVolumeNbNodes = 4
00625 //      PYRAM,     // myVolumeNbNodes = 5
00626 //      PENTA,     // myVolumeNbNodes = 6
00627 //      UNKNOWN,   // myVolumeNbNodes = 7
00628 //      HEXA       // myVolumeNbNodes = 8
00629 //    };
00630 //    return types[ myVolumeNbNodes - 4 ];
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 //function : getTetraVolume
00649 //purpose  : 
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 //function : GetSize
00685 //purpose  : Return element volume
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     // split a polyhedron into tetrahedrons
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 ); // it calls setFace()
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       // tetrahedron
00728       { 0, 1, 2, 3 },
00729       // pyramid
00730       { 0, 1, 3, 4 },
00731       { 1, 2, 3, 4 },
00732       // pentahedron
00733       { 0, 1, 2, 3 },
00734       { 1, 5, 3, 4 },
00735       { 1, 5, 2, 3 },
00736       // hexahedron
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       // quadratic tetrahedron
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       // quadratic pyramid
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       // quadratic pentahedron
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       // quadratic hexahedron
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 //function : GetBaryCenter
00826 //purpose  : 
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   // LIMITATION: for convex volumes only
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; // reverse
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 //function : SetExternalNormal
00875 //purpose  : Node order will be so that faces normals are external
00876 //=======================================================================
00877 
00878 void SMDS_VolumeTool::SetExternalNormal ()
00879 {
00880   myExternalFaces = true;
00881   myCurFace = -1;
00882 }
00883 
00884 //=======================================================================
00885 //function : NbFaceNodes
00886 //purpose  : Return number of nodes in the array of face nodes
00887 //=======================================================================
00888 
00889 int SMDS_VolumeTool::NbFaceNodes( int faceIndex )
00890 {
00891     if ( !setFace( faceIndex ))
00892       return 0;
00893     return myFaceNbNodes;
00894 }
00895 
00896 //=======================================================================
00897 //function : GetFaceNodes
00898 //purpose  : Return pointer to the array of face nodes.
00899 //           To comfort link iteration, the array
00900 //           length == NbFaceNodes( faceIndex ) + 1 and
00901 //           the last node == the first one.
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 //function : GetFaceNodesIndices
00913 //purpose  : Return pointer to the array of face nodes indices
00914 //           To comfort link iteration, the array
00915 //           length == NbFaceNodes( faceIndex ) + 1 and
00916 //           the last node index == the first one.
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 //function : GetFaceNodes
00936 //purpose  : Return a set of face nodes.
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 //function : IsFaceExternal
00955 //purpose  : Check normal orientation of a returned face
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     // only the bottom of a reversed tetrahedron can be internal
00979     return ( myVolForward || faceIndex != 0 );
00980   case 6:
00981   case 15:
00982     // in a forward pentahedron, the top is internal, in a reversed one - bottom
00983     return ( myVolForward ? faceIndex != 1 : faceIndex != 0 );
00984   case 8:
00985   case 20: {
00986     // in a forward hexahedron, even face normal is external, odd - internal
00987     bool odd = faceIndex % 2;
00988     return ( myVolForward ? !odd : odd );
00989   }
00990   default:;
00991   }
00992   return false;
00993 }
00994 
00995 //=======================================================================
00996 //function : GetFaceNormal
00997 //purpose  : Return a normal to a face
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   //if ( myFaceNbNodes == 4 ) {
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 //function : GetFaceArea
01056 //purpose  : Return face area
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 //function : GetOppFaceIndex
01086 //purpose  : Return index of the opposite face if it exists, else -1.
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 //function : IsLinked
01114 //purpose  : return true if theNode1 is linked with theNode2
01115 // If theIgnoreMediumNodes then corner nodes of quadratic cell are considered linked as well
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   // find nodes indices
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 //function : IsLinked
01165 //purpose  : return true if the node with theNode1Index is linked
01166 //           with the node with theNode2Index
01167 // If theIgnoreMediumNodes then corner nodes of quadratic cell are considered linked as well
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; // medium nodes are not linked
01190     if ( maxInd < firstMediumInd ) // both nodes are corners
01191     {
01192       if ( theIgnoreMediumNodes )
01193         type = SMDSAbs_EntityType( int(type)-1 ); // check linkage of corner nodes
01194       else
01195         return false; // corner nodes are not linked directly in a quadratic cell
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 //function : GetNodeIndex
01285 //purpose  : Return an index of theNode
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/*=0*/ )
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   // evaluate nb of face nodes shared by other volume
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; // is free
01396 
01397   // find volumes laying on the opposite side of the face
01398   // and sharing all nodes
01399   XYZ intNormal; // internal normal
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         // opposite side
01412         if ( nbShared >= nbFaceNodes )
01413         {
01414           // a volume shares the whole facet
01415           if ( otherVol ) *otherVol = vNbIt->first;
01416           return !isFree; 
01417         }
01418         ++vNbIt;
01419         continue;
01420       }
01421     }
01422     // remove a volume from volNbShared map
01423     volNbShared.erase( vNbIt++ );
01424   }
01425 
01426   // here volNbShared contains only volumes laying on the opposite side of
01427   // the face and sharing 3 or more but not all face nodes with myVolume
01428   if ( volNbShared.size() < 2 ) {
01429     return isFree; // is free
01430   }
01431 
01432   // check if the whole area of a face is shared
01433   for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
01434   {
01435     const SMDS_MeshNode* n = nodes[ iNode ];
01436     // check if n is shared by one of volumes of volNbShared
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 //   if ( !myVolume->IsPoly() )
01448 //   {
01449 //     bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle
01450 //     for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
01451 //       SMDS_VolumeTool volume( (*vNbIt).first );
01452 //       bool prevLinkShared = false;
01453 //       int nbSharedLinks = 0;
01454 //       for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
01455 //         bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] );
01456 //         if ( linkShared )
01457 //           nbSharedLinks++;
01458 //         if ( linkShared && prevLinkShared &&
01459 //              volume.IsLinked( nodes[ iNode - 1 ], nodes[ iNode + 1] ))
01460 //           isShared[ iNode ] = true;
01461 //         prevLinkShared = linkShared;
01462 //       }
01463 //       if ( nbSharedLinks == nbFaceNodes )
01464 //         return !free; // is not free
01465 //       if ( nbFaceNodes == 4 ) {
01466 //         // check traingle parts 1 & 3
01467 //         if ( isShared[1] && isShared[3] )
01468 //           return !free; // is not free
01469 //         // check triangle parts 0 & 2;
01470 //         // 0 part could not be checked in the loop; check it here
01471 //         if ( isShared[2] && prevLinkShared &&
01472 //              volume.IsLinked( nodes[ 0 ], nodes[ 1 ] ) &&
01473 //              volume.IsLinked( nodes[ 1 ], nodes[ 3 ] ) )
01474 //           return !free; // is not free
01475 //       }
01476 //     }
01477 //   }
01478 //  return free;
01479 }
01480 
01481 //=======================================================================
01482 //function : GetFaceIndex
01483 //purpose  : Return index of a face formed by theFaceNodes
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 //function : GetFaceIndex
01502 //purpose  : Return index of a face formed by theFaceNodes
01503 //=======================================================================
01504 
01505 /*int SMDS_VolumeTool::GetFaceIndex( const set<int>& theFaceNodesIndices )
01506 {
01507   for ( int iFace = 0; iFace < myNbFaces; iFace++ ) {
01508     const int* nodes = GetFaceNodesIndices( iFace );
01509     int nbFaceNodes = NbFaceNodes( iFace );
01510     set<int> nodeSet;
01511     for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
01512       nodeSet.insert( nodes[ iNode ] );
01513     if ( theFaceNodesIndices == nodeSet )
01514       return iFace;
01515   }
01516   return -1;
01517 }*/
01518 
01519 //=======================================================================
01520 //function : setFace
01521 //purpose  : 
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     // check orientation
01549     bool isGoodOri = true;
01550     if (myExternalFaces)
01551       isGoodOri = IsFaceExternal( faceIndex );
01552 
01553     // set face nodes
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 ]; // last = first
01565 
01566   }
01567   else {
01568     // choose face node indices
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     // set face nodes
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 //function : GetType
01644 //purpose  : return VolumeType by nb of nodes in a volume
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 //function : NbFaces
01664 //purpose  : return nb of faces by volume type
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 //function : GetFaceNodesIndices
01709 //purpose  : Return the array of face nodes indices
01710 //           To comfort link iteration, the array
01711 //           length == NbFaceNodes( faceIndex ) + 1 and
01712 //           the last node index == the first one.
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 //function : NbFaceNodes
01735 //purpose  : Return number of nodes in the array of face nodes
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 //function : Get
01757 //purpose  : return element
01758 //=======================================================================
01759 
01760 const SMDS_MeshVolume* SMDS_VolumeTool::Element() const
01761 {
01762   return static_cast<const SMDS_MeshVolume*>( myVolume );
01763 }
01764 
01765 //=======================================================================
01766 //function : ID
01767 //purpose  : return element ID
01768 //=======================================================================
01769 
01770 int SMDS_VolumeTool::ID() const
01771 {
01772   return myVolume ? myVolume->GetID() : 0;
01773 }
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS