X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMDS%2FSMDS_VolumeTool.cxx;h=fe3c56adc05b583ad86211243b1c73d0c81cdc42;hp=7acb3f054e3a5958f06daf8ac300fc9e4a896594;hb=ebc64f68bf3d4005762eebc43354d101670dcaed;hpb=e4737e85f0da6d3f90fd08f6be1c2825195fe16f diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index 7acb3f054..fe3c56adc 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -3,42 +3,83 @@ // Author : Edward AGAPOV (eap) // Copyright : Open CASCADE +#ifdef _MSC_VER +#pragma warning(disable:4786) +#endif #include "SMDS_VolumeTool.hxx" #include "SMDS_MeshElement.hxx" #include "SMDS_MeshNode.hxx" +#include "SMDS_PolyhedralVolumeOfNodes.hxx" + +#include "utilities.h" + #include #include +#include using namespace std; +// ====================================================== +// Node indices in faces depending on volume orientation +// making most faces normals external +// ====================================================== + /* // N3 // + // /|\ // / | \ // / | \ -// N0 +---|---+ N2 TETRAHEDRON +// N0 +---|---+ N1 TETRAHEDRON // \ | / // \ | / // \ | / // \|/ // + -// N1 +// N2 */ -static int Tetra_F [4][4] = { // FORWARD == REVERSED EXTERNAL - { 0, 1, 2, 0 }, // Bottom face has an internal normal, other - external +static int Tetra_F [4][4] = { // FORWARD == EXTERNAL + { 0, 1, 2, 0 }, // All faces have external normals + { 0, 3, 1, 0 }, + { 1, 3, 2, 1 }, + { 0, 2, 3, 0 }}; +static int Tetra_R [4][4] = { // REVERSED + { 0, 1, 2, 0 }, // All faces but a bottom have external normals { 0, 1, 3, 0 }, { 1, 2, 3, 1 }, - { 0, 3, 2, 0 }}; -static int Tetra_R [4][4] = { // REVERSED == FORWARD EXTERNAL - { 0, 2, 1, 0 }, // All faces have external normals + { 0, 3, 2, 0 }}; +static int Tetra_RE [4][4] = { // REVERSED -> FORWARD (EXTERNAL) + { 0, 2, 1, 0 }, // All faces have external normals { 0, 1, 3, 0 }, { 1, 2, 3, 1 }, - { 0, 3, 2, 0 }}; + { 0, 3, 2, 0 }}; static int Tetra_nbN [] = { 3, 3, 3, 3 }; +// +// PYRAMID +// +static int Pyramid_F [5][5] = { // FORWARD == EXTERNAL + { 0, 1, 2, 3, 0 }, // All faces have external normals + { 0, 4, 1, 0, 4 }, + { 1, 4, 2, 1, 4 }, + { 2, 4, 3, 2, 4 }, + { 3, 4, 0, 3, 4 }}; +static int Pyramid_R [5][5] = { // REVERSED + { 0, 1, 2, 3, 0 }, // All faces but a bottom have external normals + { 0, 1, 4, 0, 4 }, + { 1, 2, 4, 1, 4 }, + { 2, 3, 4, 2, 4 }, + { 3, 0, 4, 3, 4 }}; +static int Pyramid_RE [5][5] = { // REVERSED -> FORWARD (EXTERNAL) + { 0, 3, 2, 1, 0 }, // All faces but a bottom have external normals + { 0, 1, 4, 0, 4 }, + { 1, 2, 4, 1, 4 }, + { 2, 3, 4, 2, 4 }, + { 3, 0, 4, 3, 4 }}; +static int Pyramid_nbN [] = { 4, 3, 3, 3, 3 }; + /* // + N4 // /|\ @@ -58,71 +99,71 @@ static int Penta_F [5][5] = { // FORWARD { 0, 1, 2, 0, 0 }, // Top face has an internal normal, other - external { 3, 4, 5, 3, 3 }, // 0 is bottom, 1 is top face { 0, 2, 5, 3, 0 }, - { 1, 2, 5, 4, 1 }, - { 1, 0, 3, 4, 1 }}; + { 1, 4, 5, 2, 1 }, + { 0, 3, 4, 1, 0 }}; static int Penta_R [5][5] = { // REVERSED - { 0, 2, 1, 0, 0 }, // Bottom face has an internal normal, other - external - { 3, 5, 4, 3, 3 }, // 0 is bottom, 1 is top face - { 0, 2, 5, 3, 0 }, + { 0, 1, 2, 0, 0 }, // Bottom face has an internal normal, other - external + { 3, 4, 5, 3, 3 }, // 0 is bottom, 1 is top face + { 0, 3, 5, 2, 0 }, { 1, 2, 5, 4, 1 }, - { 1, 0, 3, 4, 1 }}; -static int Penta_FE [5][5] = { // EXTERNAL + { 0, 1, 4, 3, 0 }}; +static int Penta_FE [5][5] = { // FORWARD -> EXTERNAL { 0, 1, 2, 0, 0 }, { 3, 5, 4, 3, 3 }, { 0, 2, 5, 3, 0 }, + { 1, 4, 5, 2, 1 }, + { 0, 3, 4, 1, 0 }}; +static int Penta_RE [5][5] = { // REVERSED -> EXTERNAL + { 0, 2, 1, 0, 0 }, + { 3, 4, 5, 3, 3 }, + { 0, 3, 5, 2, 0 }, { 1, 2, 5, 4, 1 }, - { 1, 0, 3, 4, 1 }}; -static int Penta_RE [5][5] = { // REVERSED EXTERNAL - { 0, 0, 2, 1, 0 }, - { 3, 3, 4, 5, 3 }, - { 0, 2, 5, 3, 0 }, - { 1, 2, 5, 4, 1 }, - { 1, 0, 3, 4, 1 }}; + { 0, 1, 4, 3, 0 }}; static int Penta_nbN [] = { 3, 3, 4, 4, 4 }; /* -// N7+----------+N6 +// N5+----------+N6 // /| /| // / | / | // / | / | -// N4+----------+N5 | +// N4+----------+N7 | // | | | | HEXAHEDRON // | | | | // | | | | -// | N3+------|---+N2 +// | N1+------|---+N2 // | / | / // | / | / // |/ |/ -// N0+----------+N1 +// N0+----------+N3 */ static int Hexa_F [6][5] = { // FORWARD { 0, 1, 2, 3, 0 }, // opposite faces are neighbouring, - { 4, 5, 6, 7, 4 }, // even face normal is internal, odd - external - { 1, 0, 4, 5, 1 }, // same index nodes nodes of opposite faces are linked + { 4, 5, 6, 7, 4 }, // odd face(1,3,5) normal is internal, even(0,2,4) - external + { 1, 0, 4, 5, 1 }, // same index nodes of opposite faces are linked { 2, 3, 7, 6, 2 }, { 0, 3, 7, 4, 0 }, - { 1, 2, 6, 5, 1 }}; -static int Hexa_R [6][5] = { // REVERSED - { 0, 3, 2, 1, 0 }, // opposite faces are neighbouring, - { 4, 7, 6, 5, 4 }, // even face normal is external, odd - internal - { 1, 5, 4, 0, 1 }, // same index nodes nodes of opposite faces are linked - { 2, 6, 7, 3, 2 }, - { 0, 4, 7, 3, 0 }, - { 1, 5, 6, 2, 1 }}; -static int Hexa_FE [6][5] = { // EXTERNAL - { 0, 3, 2, 1, 0 }, // opposite faces are neighbouring, - { 4, 5, 6, 7, 4 }, // all face normals are external, - { 0, 1, 5, 4, 0 }, // links in opposite faces: 0-0, 1-3, 2-2, 3-1 - { 3, 7, 6, 2, 3 }, - { 1, 2, 6, 5, 1 }, - { 0, 4, 7, 3, 0 }}; -static int Hexa_RE [6][5] = { // REVERSED EXTERNAL - { 0, 1, 2, 3, 0 }, // opposite faces are neighbouring, - { 4, 7, 6, 5, 4 }, // all face normals are external, - { 0, 1, 5, 4, 0 }, // links in opposite faces: 0-0, 1-3, 2-2, 3-1 + { 1, 2, 6, 5, 1 }}; +// static int Hexa_R [6][5] = { // REVERSED +// { 0, 3, 2, 1, 0 }, // opposite faces are neighbouring, +// { 4, 7, 6, 5, 4 }, // odd face(1,3,5) normal is external, even(0,2,4) - internal +// { 1, 5, 4, 0, 1 }, // same index nodes of opposite faces are linked +// { 2, 6, 7, 3, 2 }, +// { 0, 4, 7, 3, 0 }, +// { 1, 5, 6, 2, 1 }}; +static int Hexa_FE [6][5] = { // FORWARD -> EXTERNAL + { 0, 1, 2, 3, 0 } , // opposite faces are neighbouring, + { 4, 7, 6, 5, 4 }, // all face normals are external, + { 0, 4, 5, 1, 0 }, // links in opposite faces: 0-0, 1-3, 2-2, 3-1 + { 3, 2, 6, 7, 3 }, + { 0, 3, 7, 4, 0 }, + { 1, 5, 6, 2, 1 }}; +static int Hexa_RE [6][5] = { // REVERSED -> EXTERNAL + { 0, 3, 2, 1, 0 }, // opposite faces are neighbouring, + { 4, 5, 6, 7, 4 }, // all face normals are external, + { 0, 1, 5, 4, 0 }, // links in opposite faces: 0-0, 1-3, 2-2, 3-1 { 3, 7, 6, 2, 3 }, - { 1, 2, 6, 5, 1 }, - { 0, 4, 7, 3, 0 }}; + { 0, 4, 7, 3, 0 }, + { 1, 2, 6, 5, 1 }}; static int Hexa_nbN [] = { 4, 4, 4, 4, 4, 4 }; // ======================================================== @@ -163,21 +204,36 @@ double XYZ::Magnitude() { SMDS_VolumeTool::SMDS_VolumeTool () : myVolume( 0 ), + myPolyedre( 0 ), myVolForward( true ), myNbFaces( 0 ), myVolumeNbNodes( 0 ), - myForwardFaces( false ), - myExternalFaces( false ) + myVolumeNodes( NULL ), + myExternalFaces( false ), + myFaceNbNodes( 0 ), + myCurFace( -1 ), + myFaceNodeIndices( NULL ), + myFaceNodes( NULL ) { } + //======================================================================= //function : SMDS_VolumeTool //purpose : //======================================================================= SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume) - : myForwardFaces( false ), - myExternalFaces( false ) + : myVolume( 0 ), + myPolyedre( 0 ), + myVolForward( true ), + myNbFaces( 0 ), + myVolumeNbNodes( 0 ), + myVolumeNodes( NULL ), + myExternalFaces( false ), + myFaceNbNodes( 0 ), + myCurFace( -1 ), + myFaceNodeIndices( NULL ), + myFaceNodes( NULL ) { Set( theVolume ); } @@ -189,6 +245,14 @@ SMDS_VolumeTool::SMDS_VolumeTool (const SMDS_MeshElement* theVolume) SMDS_VolumeTool::~SMDS_VolumeTool() { + if (myVolumeNodes != NULL) { + delete [] myVolumeNodes; + myVolumeNodes = NULL; + } + if (myFaceNodes != NULL) { + delete [] myFaceNodes; + myFaceNodes = NULL; + } } //======================================================================= @@ -199,68 +263,92 @@ SMDS_VolumeTool::~SMDS_VolumeTool() bool SMDS_VolumeTool::Set (const SMDS_MeshElement* theVolume) { myVolume = 0; + myPolyedre = 0; + myVolForward = true; - myCurFace = -1; - myVolumeNbNodes = 0; myNbFaces = 0; + myVolumeNbNodes = 0; + if (myVolumeNodes != NULL) { + delete [] myVolumeNodes; + myVolumeNodes = NULL; + } + + myExternalFaces = false; + myFaceNbNodes = 0; + + myCurFace = -1; + myFaceNodeIndices = NULL; + if (myFaceNodes != NULL) { + delete [] myFaceNodes; + myFaceNodes = NULL; + } + if ( theVolume && theVolume->GetType() == SMDSAbs_Volume ) { + myVolume = theVolume; + + myNbFaces = theVolume->NbFaces(); myVolumeNbNodes = theVolume->NbNodes(); - switch ( myVolumeNbNodes ) { - case 4: - case 6: - case 8: - { - myVolume = theVolume; - myNbFaces = theVolume->NbFaces(); - - // set volume nodes - int iNode = 0; - SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator(); - while ( nodeIt->more() ) - myVolumeNodes[ iNode++ ] = static_cast( nodeIt->next() ); - - // nb nodes in each face - if ( myVolumeNbNodes == 4 ) - myFaceNbNodes = Tetra_nbN; - else if ( myVolumeNbNodes == 6 ) - myFaceNbNodes = Penta_nbN; - else - myFaceNbNodes = Hexa_nbN; - break; - // define volume orientation - XYZ botNormal; - GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z ); - const SMDS_MeshNode* topNode = myVolumeNodes[ myVolumeNbNodes - 1 ]; - const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ]; - XYZ upDir (topNode->X() - botNode->X(), - topNode->Y() - botNode->Y(), - topNode->Z() - botNode->Z() ); - bool diffDir = ( botNormal.Dot( upDir ) < 0 ); - myVolForward = ( myVolumeNbNodes == 6 ? diffDir : !diffDir ); + // set volume nodes + int iNode = 0; + myVolumeNodes = new const SMDS_MeshNode* [myVolumeNbNodes]; + SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator(); + while ( nodeIt->more() ) { + myVolumeNodes[ iNode++ ] = static_cast( nodeIt->next() ); } - default: myVolume = 0; + + if (myVolume->IsPoly()) { + myPolyedre = static_cast( myVolume ); + if (!myPolyedre) { + MESSAGE("Warning: bad volumic element"); + return false; + } + } else { + switch ( myVolumeNbNodes ) { + case 4: + case 5: + case 6: + case 8: { + // define volume orientation + XYZ botNormal; + GetFaceNormal( 0, botNormal.x, botNormal.y, botNormal.z ); + const SMDS_MeshNode* topNode = myVolumeNodes[ myVolumeNbNodes - 1 ]; + const SMDS_MeshNode* botNode = myVolumeNodes[ 0 ]; + XYZ upDir (topNode->X() - botNode->X(), + topNode->Y() - botNode->Y(), + topNode->Z() - botNode->Z() ); + myVolForward = ( botNormal.Dot( upDir ) < 0 ); + break; + } + default: + break; + } } } return ( myVolume != 0 ); } //======================================================================= -//function : GetInverseNodes -//purpose : Return nodes vector of an inverse volume +//function : Inverse +//purpose : Inverse volume //======================================================================= -#define SWAP_NODES(nodes,i1,i2) \ -{ \ +#define SWAP_NODES(nodes,i1,i2) \ +{ \ const SMDS_MeshNode* tmp = nodes[ i1 ]; \ - nodes[ i1 ] = nodes[ i2 ]; \ + nodes[ i1 ] = nodes[ i2 ]; \ nodes[ i2 ] = tmp; \ } void SMDS_VolumeTool::Inverse () { if ( !myVolume ) return; + if (myVolume->IsPoly()) { + MESSAGE("Warning: attempt to inverse polyhedral volume"); + return; + } + myVolForward = !myVolForward; myCurFace = -1; @@ -269,6 +357,9 @@ void SMDS_VolumeTool::Inverse () case 4: SWAP_NODES( myVolumeNodes, 1, 2 ); break; + case 5: + SWAP_NODES( myVolumeNodes, 1, 3 ); + break; case 6: SWAP_NODES( myVolumeNodes, 1, 2 ); SWAP_NODES( myVolumeNodes, 4, 5 ); @@ -314,16 +405,6 @@ bool SMDS_VolumeTool::GetBaryCenter(double & X, double & Y, double & Z) const return true; } -//======================================================================= -//function : SetForwardOrientation -//purpose : Node order will be as for forward orientation -//======================================================================= - -void SMDS_VolumeTool::SetForwardOrientation () -{ - myForwardFaces = true; -} - //======================================================================= //function : SetExternalNormal //purpose : Node order will be so that faces normals are external @@ -332,6 +413,7 @@ void SMDS_VolumeTool::SetForwardOrientation () void SMDS_VolumeTool::SetExternalNormal () { myExternalFaces = true; + myCurFace = -1; } //======================================================================= @@ -341,9 +423,9 @@ void SMDS_VolumeTool::SetExternalNormal () int SMDS_VolumeTool::NbFaceNodes( int faceIndex ) { - if ( !setFace( faceIndex )) - return 0; - return myFaceNbNodes[ faceIndex ]; + if ( !setFace( faceIndex )) + return 0; + return myFaceNbNodes; } //======================================================================= @@ -371,6 +453,10 @@ const SMDS_MeshNode** SMDS_VolumeTool::GetFaceNodes( int faceIndex ) const int* SMDS_VolumeTool::GetFaceNodesIndices( int faceIndex ) { + if (myVolume->IsPoly()) { + MESSAGE("Warning: attempt to obtain FaceNodesIndices of polyhedral volume"); + return NULL; + } if ( !setFace( faceIndex )) return 0; return myFaceNodeIndices; @@ -381,17 +467,17 @@ const int* SMDS_VolumeTool::GetFaceNodesIndices( int faceIndex ) //purpose : Return a set of face nodes. //======================================================================= -bool SMDS_VolumeTool::GetFaceNodes (int faceIndex, - std::set& theFaceNodes ) +bool SMDS_VolumeTool::GetFaceNodes (int faceIndex, + set& theFaceNodes ) { if ( !setFace( faceIndex )) return false; theFaceNodes.clear(); - int iNode, nbNode = myFaceNbNodes[ faceIndex ]; - for ( int iNode = 0; iNode < nbNode; iNode++ ) + int iNode, nbNode = myFaceNbNodes; + for ( iNode = 0; iNode < nbNode; iNode++ ) theFaceNodes.insert( myFaceNodes[ iNode ]); - + return true; } @@ -405,18 +491,28 @@ bool SMDS_VolumeTool::IsFaceExternal( int faceIndex ) if ( myExternalFaces || !myVolume ) return true; - bool reversed = ( !myForwardFaces && !myVolForward ); + if (myVolume->IsPoly()) { + XYZ aNormal, baryCenter, p0 (myPolyedre->GetFaceNode(faceIndex + 1, 1)); + GetFaceNormal(faceIndex, aNormal.x, aNormal.y, aNormal.z); + GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z); + XYZ insideVec (baryCenter - p0); + if (insideVec.Dot(aNormal) > 0) + return false; + return true; + } + switch ( myVolumeNbNodes ) { case 4: - // only the bottom of a forward tetrahedron can be internal - return ( reversed || faceIndex != 0 ); + case 5: + // only the bottom of a reversed tetrahedron can be internal + return ( myVolForward || faceIndex != 0 ); case 6: // in a forward pentahedron, the top is internal, in a reversed one - bottom - return ( reversed ? faceIndex != 0 : faceIndex != 1 ); + return ( myVolForward ? faceIndex != 1 : faceIndex != 0 ); case 8: { - // in a forward hexahedron, odd face normal is external, else vice versa + // in a forward hexahedron, even face normal is external, odd - internal bool odd = faceIndex % 2; - return ( reversed ? !odd : odd ); + return ( myVolForward ? !odd : odd ); } default:; } @@ -440,6 +536,15 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub XYZ aVec13( p3 - p1 ); XYZ cross = aVec12.Crossed( aVec13 ); + if ( myFaceNbNodes == 4 ) { + XYZ p4 ( myFaceNodes[3] ); + XYZ aVec14( p4 - p1 ); + XYZ cross2 = aVec13.Crossed( aVec14 ); + cross.x += cross2.x; + cross.y += cross2.y; + cross.z += cross2.z; + } + double size = cross.Magnitude(); if ( size <= DBL_MIN ) return false; @@ -451,7 +556,6 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub return true; } - //======================================================================= //function : GetFaceArea //purpose : Return face area @@ -459,6 +563,11 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub double SMDS_VolumeTool::GetFaceArea( int faceIndex ) { + if (myVolume->IsPoly()) { + MESSAGE("Warning: attempt to obtain area of a face of polyhedral volume"); + return 0; + } + if ( !setFace( faceIndex )) return 0; @@ -469,7 +578,7 @@ double SMDS_VolumeTool::GetFaceArea( int faceIndex ) XYZ aVec13( p3 - p1 ); double area = aVec12.Crossed( aVec13 ).Magnitude() * 0.5; - if ( myFaceNbNodes[ faceIndex ] == 4 ) { + if ( myFaceNbNodes == 4 ) { XYZ p4 ( myFaceNodes[3] ); XYZ aVec14( p4 - p1 ); area += aVec14.Crossed( aVec13 ).Magnitude() * 0.5; @@ -485,12 +594,17 @@ double SMDS_VolumeTool::GetFaceArea( int faceIndex ) int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const { int ind = -1; + if (myVolume->IsPoly()) { + MESSAGE("Warning: attempt to obtain opposite face on polyhedral volume"); + return ind; + } + if ( faceIndex >= 0 && faceIndex < NbFaces() ) { switch ( myVolumeNbNodes ) { case 6: if ( faceIndex == 0 || faceIndex == 1 ) ind = 1 - faceIndex; - break; + break; case 8: ind = faceIndex + ( faceIndex % 2 ? -1 : 1 ); break; @@ -511,6 +625,33 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1, if ( !myVolume ) return false; + if (myVolume->IsPoly()) { + if (!myPolyedre) { + MESSAGE("Warning: bad volumic element"); + return false; + } + bool isLinked = false; + int iface; + for (iface = 1; iface <= myNbFaces && !isLinked; iface++) { + int inode, nbFaceNodes = myPolyedre->NbFaceNodes(iface); + + for (inode = 1; inode <= nbFaceNodes && !isLinked; inode++) { + const SMDS_MeshNode* curNode = myPolyedre->GetFaceNode(iface, inode); + + if (curNode == theNode1 || curNode == theNode2) { + int inextnode = (inode == nbFaceNodes) ? 1 : inode + 1; + const SMDS_MeshNode* nextNode = myPolyedre->GetFaceNode(iface, inextnode); + + if ((curNode == theNode1 && nextNode == theNode2) || + (curNode == theNode2 && nextNode == theNode1)) { + isLinked = true; + } + } + } + } + return isLinked; + } + // find nodes indices int i1 = -1, i2 = -1; for ( int i = 0; i < myVolumeNbNodes; i++ ) { @@ -531,6 +672,10 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1, bool SMDS_VolumeTool::IsLinked (const int theNode1Index, const int theNode2Index) const { + if (myVolume->IsPoly()) { + return IsLinked(myVolumeNodes[theNode1Index], myVolumeNodes[theNode2Index]); + } + int minInd = theNode1Index < theNode2Index ? theNode1Index : theNode2Index; int maxInd = theNode1Index < theNode2Index ? theNode2Index : theNode1Index; @@ -540,6 +685,15 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index, switch ( myVolumeNbNodes ) { case 4: return true; + case 5: + if ( maxInd == 4 ) + return true; + switch ( maxInd - minInd ) { + case 1: + case 3: return true; + default:; + } + break; case 6: switch ( maxInd - minInd ) { case 1: return minInd != 2; @@ -577,7 +731,6 @@ int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const return -1; } - //======================================================================= //function : IsFreeFace //purpose : check that only one volume is build on the face nodes @@ -586,11 +739,12 @@ int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) { const int free = true; - if ( !setFace( faceIndex )) + + if (!setFace( faceIndex )) return !free; const SMDS_MeshNode** nodes = GetFaceNodes( faceIndex ); - int nbFaceNodes = NbFaceNodes( faceIndex ); + int nbFaceNodes = myFaceNbNodes; // evaluate nb of face nodes shared by other volume int maxNbShared = -1; @@ -666,7 +820,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex ) // check traingle parts 1 & 3 if ( isShared[1] && isShared[3] ) return !free; // is not free - // check traingle parts 0 & 2; + // check triangle parts 0 & 2; // 0 part could not be checked in the loop; check it here if ( isShared[2] && prevLinkShared && volume.IsLinked( nodes[ 0 ], nodes[ 1 ] ) && @@ -701,7 +855,7 @@ int SMDS_VolumeTool::GetFaceIndex( const set& theFaceNodes //purpose : Return index of a face formed by theFaceNodes //======================================================================= -int SMDS_VolumeTool::GetFaceIndex( const set& theFaceNodesIndices ) +/*int SMDS_VolumeTool::GetFaceIndex( const set& theFaceNodesIndices ) { for ( int iFace = 0; iFace < myNbFaces; iFace++ ) { const int* nodes = GetFaceNodesIndices( iFace ); @@ -713,7 +867,7 @@ int SMDS_VolumeTool::GetFaceIndex( const set& theFaceNodesIndices ) return iFace; } return -1; -} +}*/ //======================================================================= //function : setFace @@ -728,44 +882,164 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) if ( myCurFace == faceIndex ) return true; + myCurFace = -1; + if ( faceIndex < 0 || faceIndex >= NbFaces() ) return false; - // choose face node indices - switch ( myVolumeNbNodes ) { - case 4: - if ( myExternalFaces ) - myFaceNodeIndices = myVolForward ? Tetra_R[ faceIndex ] : Tetra_F[ faceIndex ]; - else if ( myForwardFaces ) - myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_R[ faceIndex ]; - else - myFaceNodeIndices = Tetra_F[ faceIndex ]; - break; - case 6: - if ( myExternalFaces ) - myFaceNodeIndices = myVolForward ? Penta_FE[ faceIndex ] : Penta_RE[ faceIndex ]; - else if ( myForwardFaces ) - myFaceNodeIndices = myVolForward ? Penta_F[ faceIndex ] : Penta_R[ faceIndex ]; - else - myFaceNodeIndices = Penta_F[ faceIndex ]; - break; - case 8: - if ( myExternalFaces ) - myFaceNodeIndices = myVolForward ? Hexa_FE[ faceIndex ] : Hexa_RE[ faceIndex ]; - else if ( myForwardFaces ) - myFaceNodeIndices = myVolForward ? Hexa_F[ faceIndex ] : Hexa_R[ faceIndex ]; - else - myFaceNodeIndices = Hexa_F[ faceIndex ]; - break; - default: return false; + if (myFaceNodes != NULL) { + delete [] myFaceNodes; + myFaceNodes = NULL; } - // set face nodes - int iNode, nbNode = myFaceNbNodes[ faceIndex ]; - for ( iNode = 0; iNode <= nbNode; iNode++ ) - myFaceNodes[ iNode ] = myVolumeNodes[ myFaceNodeIndices[ iNode ]]; + if (myVolume->IsPoly()) { + if (!myPolyedre) { + MESSAGE("Warning: bad volumic element"); + return false; + } + + // check orientation + bool isGoodOri = true; + if (myExternalFaces) { + // get natural orientation + XYZ aNormal, baryCenter, p0 (myPolyedre->GetFaceNode(faceIndex + 1, 1)); + SMDS_VolumeTool vTool (myPolyedre); + vTool.GetFaceNormal(faceIndex, aNormal.x, aNormal.y, aNormal.z); + vTool.GetBaryCenter(baryCenter.x, baryCenter.y, baryCenter.z); + XYZ insideVec (baryCenter - p0); + if (insideVec.Dot(aNormal) > 0) + isGoodOri = false; + } + + // set face nodes + int iNode; + myFaceNbNodes = myPolyedre->NbFaceNodes(faceIndex + 1); + myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1]; + if (isGoodOri) { + for ( iNode = 0; iNode < myFaceNbNodes; iNode++ ) + myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, iNode + 1); + } else { + for ( iNode = 0; iNode < myFaceNbNodes; iNode++ ) + myFaceNodes[ iNode ] = myPolyedre->GetFaceNode(faceIndex + 1, myFaceNbNodes - iNode); + } + myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ]; // last = first + + } else { + // choose face node indices + switch ( myVolumeNbNodes ) { + case 4: + myFaceNbNodes = Tetra_nbN[ faceIndex ]; + if ( myExternalFaces ) + myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_RE[ faceIndex ]; + else + myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_R[ faceIndex ]; + break; + case 5: + myFaceNbNodes = Pyramid_nbN[ faceIndex ]; + if ( myExternalFaces ) + myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_RE[ faceIndex ]; + else + myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_R[ faceIndex ]; + break; + case 6: + myFaceNbNodes = Penta_nbN[ faceIndex ]; + if ( myExternalFaces ) + myFaceNodeIndices = myVolForward ? Penta_FE[ faceIndex ] : Penta_RE[ faceIndex ]; + else + myFaceNodeIndices = myVolForward ? Penta_F[ faceIndex ] : Penta_R[ faceIndex ]; + break; + case 8: + myFaceNbNodes = Hexa_nbN[ faceIndex ]; + if ( myExternalFaces ) + myFaceNodeIndices = myVolForward ? Hexa_FE[ faceIndex ] : Hexa_RE[ faceIndex ]; + else + myFaceNodeIndices = Hexa_F[ faceIndex ]; + break; + default: + return false; + } + + // set face nodes + myFaceNodes = new const SMDS_MeshNode* [myFaceNbNodes + 1]; + for ( int iNode = 0; iNode < myFaceNbNodes; iNode++ ) + myFaceNodes[ iNode ] = myVolumeNodes[ myFaceNodeIndices[ iNode ]]; + myFaceNodes[ myFaceNbNodes ] = myFaceNodes[ 0 ]; + } myCurFace = faceIndex; return true; } + +//======================================================================= +//function : GetType +//purpose : return VolumeType by nb of nodes in a volume +//======================================================================= + +SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetType(int nbNodes) +{ + switch ( nbNodes ) { + case 4: return TETRA; + case 5: return PYRAM; + case 6: return PENTA; + case 8: return HEXA; + default:return UNKNOWN; + } +} + +//======================================================================= +//function : NbFaces +//purpose : return nb of faces by volume type +//======================================================================= + +int SMDS_VolumeTool::NbFaces( VolumeType type ) +{ + switch ( type ) { + case TETRA: return 4; + case PYRAM: return 5; + case PENTA: return 5; + case HEXA : return 6; + default: return 0; + } +} + +//======================================================================= +//function : GetFaceNodesIndices +//purpose : Return the array of face nodes indices +// To comfort link iteration, the array +// length == NbFaceNodes( faceIndex ) + 1 and +// the last node index == the first one. +//======================================================================= + +const int* SMDS_VolumeTool::GetFaceNodesIndices(VolumeType type, + int faceIndex, + bool external) +{ + switch ( type ) { + case TETRA: return Tetra_F[ faceIndex ]; + case PYRAM: return Pyramid_F[ faceIndex ]; + case PENTA: return external ? Penta_FE[ faceIndex ] : Penta_F[ faceIndex ]; + case HEXA: return external ? Hexa_FE[ faceIndex ] : Hexa_F[ faceIndex ]; + default:; + } + return 0; +} + +//======================================================================= +//function : NbFaceNodes +//purpose : Return number of nodes in the array of face nodes +//======================================================================= + +int SMDS_VolumeTool::NbFaceNodes(VolumeType type, + int faceIndex ) +{ + switch ( type ) { + case TETRA: return Tetra_nbN[ faceIndex ]; + case PYRAM: return Pyramid_nbN[ faceIndex ]; + case PENTA: return Penta_nbN[ faceIndex ]; + case HEXA: return Hexa_nbN[ faceIndex ]; + default:; + } + return 0; +} +