VolumeTool has been partially adapted for PolyhedralVolumes processing

This commit is contained in:
jfa 2005-03-02 12:34:34 +00:00
parent 52edf90f5a
commit 10df32bae6
2 changed files with 246 additions and 91 deletions

View File

@ -11,6 +11,10 @@
#include "SMDS_MeshElement.hxx"
#include "SMDS_MeshNode.hxx"
#include "SMDS_PolyhedralVolumeOfNodes.hxx"
#include "utilities.h"
#include <map>
#include <float.h>
#include <math.h>
@ -200,19 +204,36 @@ double XYZ::Magnitude() {
SMDS_VolumeTool::SMDS_VolumeTool ()
: myVolume( 0 ),
myPolyedre( 0 ),
myVolForward( true ),
myNbFaces( 0 ),
myVolumeNbNodes( 0 ),
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)
: 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 );
}
@ -224,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;
}
}
//=======================================================================
@ -234,58 +263,75 @@ 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 5:
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<const SMDS_MeshNode*>( nodeIt->next() );
// nb nodes in each face
if ( myVolumeNbNodes == 4 )
myFaceNbNodes = Tetra_nbN;
else if ( myVolumeNbNodes == 5 )
myFaceNbNodes = Pyramid_nbN;
else if ( myVolumeNbNodes == 6 )
myFaceNbNodes = Penta_nbN;
else
myFaceNbNodes = Hexa_nbN;
// 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;
// set volume nodes
int iNode = 0;
myVolumeNodes = new const SMDS_MeshNode* [myVolumeNbNodes];
SMDS_ElemIteratorPtr nodeIt = myVolume->nodesIterator();
while ( nodeIt->more() ) {
myVolumeNodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
}
default: myVolume = 0;
if (myVolume->IsPoly()) {
myPolyedre = static_cast<const SMDS_PolyhedralVolumeOfNodes*>( 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) \
@ -298,6 +344,11 @@ void SMDS_VolumeTool::Inverse ()
{
if ( !myVolume ) return;
if (myVolume->IsPoly()) {
MESSAGE("Warning: attempt to inverse polyhedral volume");
return;
}
myVolForward = !myVolForward;
myCurFace = -1;
@ -372,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;
}
//=======================================================================
@ -402,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;
@ -419,10 +474,10 @@ bool SMDS_VolumeTool::GetFaceNodes (int faceIndex,
return false;
theFaceNodes.clear();
int iNode, nbNode = myFaceNbNodes[ faceIndex ];
int iNode, nbNode = myFaceNbNodes;
for ( iNode = 0; iNode < nbNode; iNode++ )
theFaceNodes.insert( myFaceNodes[ iNode ]);
return true;
}
@ -436,6 +491,16 @@ bool SMDS_VolumeTool::IsFaceExternal( int faceIndex )
if ( myExternalFaces || !myVolume )
return true;
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:
case 5:
@ -482,7 +547,6 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub
return true;
}
//=======================================================================
//function : GetFaceArea
//purpose : Return face area
@ -490,6 +554,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;
@ -500,7 +569,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;
@ -516,12 +585,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;
@ -542,6 +616,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++ ) {
@ -562,6 +663,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;
@ -617,7 +722,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
@ -626,11 +730,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;
@ -706,7 +811,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 ] ) &&
@ -741,7 +846,7 @@ int SMDS_VolumeTool::GetFaceIndex( const set<const SMDS_MeshNode*>& theFaceNodes
//purpose : Return index of a face formed by theFaceNodes
//=======================================================================
int SMDS_VolumeTool::GetFaceIndex( const set<int>& theFaceNodesIndices )
/*int SMDS_VolumeTool::GetFaceIndex( const set<int>& theFaceNodesIndices )
{
for ( int iFace = 0; iFace < myNbFaces; iFace++ ) {
const int* nodes = GetFaceNodesIndices( iFace );
@ -753,7 +858,7 @@ int SMDS_VolumeTool::GetFaceIndex( const set<int>& theFaceNodesIndices )
return iFace;
}
return -1;
}
}*/
//=======================================================================
//function : setFace
@ -768,42 +873,88 @@ 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_F[ faceIndex ] : Tetra_RE[ faceIndex ];
else
myFaceNodeIndices = myVolForward ? Tetra_F[ faceIndex ] : Tetra_R[ faceIndex ];
break;
case 5:
if ( myExternalFaces )
myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_RE[ faceIndex ];
else
myFaceNodeIndices = myVolForward ? Pyramid_F[ faceIndex ] : Pyramid_R[ faceIndex ];
break;
case 6:
if ( myExternalFaces )
myFaceNodeIndices = myVolForward ? Penta_FE[ faceIndex ] : Penta_RE[ faceIndex ];
else
myFaceNodeIndices = myVolForward ? Penta_F[ faceIndex ] : Penta_R[ faceIndex ];
break;
case 8:
if ( myExternalFaces )
myFaceNodeIndices = myVolForward ? Hexa_FE[ faceIndex ] : Hexa_RE[ 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 ]];
}
myCurFace = faceIndex;

View File

@ -32,6 +32,7 @@
class SMDS_MeshElement;
class SMDS_MeshNode;
class SMDS_PolyhedralVolumeOfNodes;
#include <vector>
#include <set>
@ -149,7 +150,7 @@ class SMDS_VolumeTool
// Return index of a face formed by theFaceNodes.
// Return -1 if a face not found
int GetFaceIndex( const std::set<int>& theFaceNodesIndices );
//int GetFaceIndex( const std::set<int>& theFaceNodesIndices );
// Return index of a face formed by theFaceNodesIndices
// Return -1 if a face not found
@ -159,16 +160,19 @@ class SMDS_VolumeTool
bool setFace( int faceIndex );
const SMDS_MeshElement* myVolume;
const SMDS_PolyhedralVolumeOfNodes* myPolyedre;
bool myVolForward;
int myNbFaces;
int myVolumeNbNodes;
const SMDS_MeshNode* myVolumeNodes[ 8 ];
const SMDS_MeshNode** myVolumeNodes;
bool myExternalFaces;
int* myFaceNodeIndices;
int* myFaceNbNodes;
const SMDS_MeshNode* myFaceNodes[ 5 ];
int myCurFace;
int myFaceNbNodes;
int* myFaceNodeIndices;
const SMDS_MeshNode** myFaceNodes;
};
#endif