Salome HOME
Merge from V5_1_main 14/05/2010
[modules/smesh.git] / src / SMDS / SMDS_VolumeTool.cxx
index 9f35e015818776d4b5f64f2383a56492ebdd2086..52633d6107bfa35f18162884796c627df7e3704e 100644 (file)
@@ -1,27 +1,29 @@
-// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either 
-// version 2.1 of the License.
-// 
-// This library is distributed in the hope that it will be useful 
-// but WITHOUT ANY WARRANTY; without even the implied warranty of 
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-// Lesser General Public License for more details.
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-// You should have received a copy of the GNU Lesser General Public  
-// License along with this library; if not, write to the Free Software 
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-// See http://www.salome-platform.org/
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
 // File      : SMDS_VolumeTool.cxx
 // Created   : Tue Jul 13 12:22:13 2004
 // Author    : Edward AGAPOV (eap)
-// Copyright : Open CASCADE
-
+//
 #ifdef _MSC_VER
 #pragma warning(disable:4786)
 #endif
@@ -31,6 +33,7 @@
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
+#include "SMDS_Mesh.hxx"
 
 #include "utilities.h"
 
@@ -366,6 +369,8 @@ static int QuadHexa_nbN [] = { 8, 8, 8, 8, 8, 8 };
 // ========================================================
 // to perform some calculations without linkage to CASCADE
 // ========================================================
+namespace
+{
 struct XYZ {
   double x;
   double y;
@@ -374,25 +379,26 @@ struct XYZ {
   XYZ( double X, double Y, double Z ) { x = X; y = Y; z = Z; }
   XYZ( const XYZ& other )             { x = other.x; y = other.y; z = other.z; }
   XYZ( const SMDS_MeshNode* n )       { x = n->X(); y = n->Y(); z = n->Z(); }
-  XYZ operator-( const XYZ& other );
-  XYZ Crossed( const XYZ& other );
-  double Dot( const XYZ& other );
-  double Magnitude();
+  inline XYZ operator-( const XYZ& other );
+  inline XYZ Crossed( const XYZ& other );
+  inline double Dot( const XYZ& other );
+  inline double Magnitude();
 };
-XYZ XYZ::operator-( const XYZ& Right ) {
+inline XYZ XYZ::operator-( const XYZ& Right ) {
   return XYZ(x - Right.x, y - Right.y, z - Right.z);
 }
-XYZ XYZ::Crossed( const XYZ& Right ) {
+inline XYZ XYZ::Crossed( const XYZ& Right ) {
   return XYZ (y * Right.z - z * Right.y,
               z * Right.x - x * Right.z,
               x * Right.y - y * Right.x);
 }
-double XYZ::Dot( const XYZ& Other ) {
+inline double XYZ::Dot( const XYZ& Other ) {
   return(x * Other.x + y * Other.y + z * Other.z);
 }
-double XYZ::Magnitude() {
+inline double XYZ::Magnitude() {
   return sqrt (x * x + y * y + z * z);
 }
+}
 
 //=======================================================================
 //function : SMDS_VolumeTool
@@ -442,14 +448,11 @@ 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;
-  }
+  if ( myVolumeNodes != NULL ) delete [] myVolumeNodes;
+  if ( myFaceNodes != NULL   ) delete [] myFaceNodes;
+
+  myFaceNodeIndices = NULL;
+  myVolumeNodes = myFaceNodes = NULL;
 }
 
 //=======================================================================
@@ -835,6 +838,32 @@ bool SMDS_VolumeTool::GetBaryCenter(double & X, double & Y, double & Z) const
   return true;
 }
 
+//================================================================================
+/*!
+ * \brief Classify a point
+ *  \param tol - thickness of faces
+ */
+//================================================================================
+
+bool SMDS_VolumeTool::IsOut(double X, double Y, double Z, double tol)
+{
+  // LIMITATION: for convex volumes only
+  XYZ p( X,Y,Z );
+  for ( int iF = 0; iF < myNbFaces; ++iF )
+  {
+    XYZ faceNormal;
+    if ( !GetFaceNormal( iF, faceNormal.x, faceNormal.y, faceNormal.z ))
+      continue;
+    if ( !IsFaceExternal( iF ))
+      faceNormal = XYZ() - faceNormal; // reverse
+
+    XYZ face2p( p - XYZ( myFaceNodes[0] ));
+    if ( face2p.Dot( faceNormal ) > tol )
+      return true;
+  }
+  return false;
+}
+
 //=======================================================================
 //function : SetExternalNormal
 //purpose  : Node order will be so that faces normals are external
@@ -883,12 +912,16 @@ 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;
+
+  if (myVolume->IsPoly())
+  {
+    myPolyIndices.resize( myFaceNbNodes + 1 );
+    myFaceNodeIndices = & myPolyIndices[0];
+    for ( int i = 0; i <= myFaceNbNodes; ++i )
+      myFaceNodeIndices[i] = myVolume->GetNodeIndex( myFaceNodes[i] );
+  }
   return myFaceNodeIndices;
 }
 
@@ -1111,8 +1144,8 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
     return IsLinked(myVolumeNodes[theNode1Index], myVolumeNodes[theNode2Index]);
   }
 
-  int minInd = theNode1Index < theNode2Index ? theNode1Index : theNode2Index;
-  int maxInd = theNode1Index < theNode2Index ? theNode2Index : theNode1Index;
+  int minInd = min( theNode1Index, theNode2Index );
+  int maxInd = max( theNode1Index, theNode2Index );
 
   if ( minInd < 0 || maxInd > myVolumeNbNodes - 1 || maxInd == minInd )
     return false;
@@ -1217,6 +1250,65 @@ int SMDS_VolumeTool::GetNodeIndex(const SMDS_MeshNode* theNode) const
   return -1;
 }
 
+//================================================================================
+/*!
+ * \brief Fill vector with boundary faces existing in the mesh
+  * \param faces - vector of found nodes
+  * \retval int - nb of found faces
+ */
+//================================================================================
+
+int SMDS_VolumeTool::GetAllExistingFaces(vector<const SMDS_MeshElement*> & faces)
+{
+  faces.clear();
+  faces.reserve( NbFaces() );
+  for ( int iF = 0; iF < NbFaces(); ++iF ) {
+    const SMDS_MeshFace* face = 0;
+    const SMDS_MeshNode** nodes = GetFaceNodes( iF );
+    switch ( NbFaceNodes( iF )) {
+    case 3:
+      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2] ); break;
+    case 4:
+      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3] ); break;
+    case 6:
+      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2],
+                                  nodes[3], nodes[4], nodes[5]); break;
+    case 8:
+      face = SMDS_Mesh::FindFace( nodes[0], nodes[1], nodes[2], nodes[3],
+                                  nodes[4], nodes[5], nodes[6], nodes[7]); break;
+    }
+    if ( face )
+      faces.push_back( face );
+  }
+  return faces.size();
+}
+
+
+//================================================================================
+/*!
+ * \brief Fill vector with boundary edges existing in the mesh
+  * \param edges - vector of found edges
+  * \retval int - nb of found faces
+ */
+//================================================================================
+
+int SMDS_VolumeTool::GetAllExistingEdges(vector<const SMDS_MeshElement*> & edges) const
+{
+  edges.clear();
+  edges.reserve( myVolumeNbNodes * 2 );
+  for ( int i = 0; i < myVolumeNbNodes; ++i ) {
+    for ( int j = i + 1; j < myVolumeNbNodes; ++j ) {
+      if ( IsLinked( i, j )) {
+        const SMDS_MeshElement* edge =
+          SMDS_Mesh::FindEdge( myVolumeNodes[i], myVolumeNodes[j] );
+        if ( edge )
+          edges.push_back( edge );
+      }
+    }
+  }
+  return edges.size();
+}
+
 //=======================================================================
 //function : IsFreeFace
 //purpose  : check that only one volume is build on the face nodes
@@ -1276,7 +1368,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
         continue; // opposite side
     }
     // remove a volume from volNbShared map
-    volNbShared.erase( vNbIt );
+    volNbShared.erase( vNbIt-- );
   }
 
   // here volNbShared contains only volumes laying on the
@@ -1518,6 +1610,31 @@ int SMDS_VolumeTool::NbFaces( VolumeType type )
   }
 }
 
+//================================================================================
+/*!
+ * \brief Useful to know nb of corner nodes of a quadratic volume
+  * \param type - volume type
+  * \retval int - nb of corner nodes
+ */
+//================================================================================
+
+int SMDS_VolumeTool::NbCornerNodes(VolumeType type)
+{
+  switch ( type ) {
+  case TETRA     :
+  case QUAD_TETRA: return 4;
+  case PYRAM     :
+  case QUAD_PYRAM: return 5;
+  case PENTA     :
+  case QUAD_PENTA: return 6;
+  case HEXA      :
+  case QUAD_HEXA : return 8;
+  default:    return 0;
+  }
+  return 0;
+}
+  // 
+
 //=======================================================================
 //function : GetFaceNodesIndices
 //purpose  : Return the array of face nodes indices
@@ -1566,3 +1683,22 @@ int SMDS_VolumeTool::NbFaceNodes(VolumeType type,
   return 0;
 }
 
+//=======================================================================
+//function : Get
+//purpose  : return element
+//=======================================================================
+
+const SMDS_MeshVolume* SMDS_VolumeTool::Element() const
+{
+  return static_cast<const SMDS_MeshVolume*>( myVolume );
+}
+
+//=======================================================================
+//function : ID
+//purpose  : return element ID
+//=======================================================================
+
+int SMDS_VolumeTool::ID() const
+{
+  return myVolume ? myVolume->GetID() : 0;
+}