Salome HOME
Update copyrights
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index f86b5638719dfb201d6e15ab0a6e4487a1b0f174..f18cadd34e8b27efae988682a905489a7b505afc 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -28,8 +28,6 @@
 #include "SMDS_Mesh.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
-#include "SMDS_QuadraticEdge.hxx"
-#include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMESHDS_GroupBase.hxx"
 #include "SMESHDS_GroupOnFilter.hxx"
@@ -235,7 +233,7 @@ bool NumericalFunctor::GetPoints(const int       theId,
     return false;
 
   const SMDS_MeshElement* anElem = myMesh->FindElement( theId );
-  if ( !anElem || anElem->GetType() != this->GetType() )
+  if ( !IsApplicable( anElem ))
     return false;
 
   return GetPoints( anElem, theRes );
@@ -253,26 +251,7 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
   theRes.setElement( anElem );
 
   // Get nodes of the element
-  SMDS_ElemIteratorPtr anIter;
-
-  if ( anElem->IsQuadratic() ) {
-    switch ( anElem->GetType() ) {
-    case SMDSAbs_Edge:
-      anIter = dynamic_cast<const SMDS_VtkEdge*>
-        (anElem)->interlacedNodesElemIterator();
-      break;
-    case SMDSAbs_Face:
-      anIter = dynamic_cast<const SMDS_VtkFace*>
-        (anElem)->interlacedNodesElemIterator();
-      break;
-    default:
-      anIter = anElem->nodesIterator();
-    }
-  }
-  else {
-    anIter = anElem->nodesIterator();
-  }
-
+  SMDS_NodeIteratorPtr anIter= anElem->interlacedNodesIterator();
   if ( anIter ) {
     SMESH_NodeXYZ p;
     while( anIter->more() ) {
@@ -313,6 +292,24 @@ double NumericalFunctor::Round( const double & aVal )
   return ( myPrecision >= 0 ) ? floor( aVal * myPrecisionValue + 0.5 ) / myPrecisionValue : aVal;
 }
 
+//================================================================================
+/*!
+ * \brief Return true if a value can be computed for a given element.
+ *        Some NumericalFunctor's are meaningful for elements of a certain
+ *        geometry only.
+ */
+//================================================================================
+
+bool NumericalFunctor::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return element && element->GetType() == this->GetType();
+}
+
+bool NumericalFunctor::IsApplicable( long theElementId ) const
+{
+  return IsApplicable( myMesh->FindElement( theElementId ));
+}
+
 //================================================================================
 /*!
  * \brief Return histogram of functor values
@@ -771,8 +768,8 @@ double AspectRatio::GetValue( long theId )
   if ( myCurrElement && myCurrElement->GetVtkType() == VTK_QUAD )
   {
     // issue 21723
-    vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myCurrElement->getMeshId()]->getGrid();
-    if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->getVtkId() ))
+    vtkUnstructuredGrid* grid = const_cast<SMDS_Mesh*>( myMesh )->GetGrid();
+    if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() ))
       aVal = Round( vtkMeshQuality::QuadAspectRatio( avtkCell ));
   }
   else
@@ -922,6 +919,11 @@ double AspectRatio::GetValue( const TSequenceOfXYZ& P )
   return 0;
 }
 
+bool AspectRatio::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return ( NumericalFunctor::IsApplicable( element ) && !element->IsPoly() );
+}
+
 double AspectRatio::GetBadRate( double Value, int /*nbNodes*/ ) const
 {
   // the aspect ratio is in the range [1.0,infinity]
@@ -1015,8 +1017,8 @@ double AspectRatio3D::GetValue( long theId )
     // Action from CoTech | ACTION 31.3:
     // EURIWARE BO: Homogenize the formulas used to calculate the Controls in SMESH to fit with
     // those of ParaView. The library used by ParaView for those calculations can be reused in SMESH.
-    vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myCurrElement->getMeshId()]->getGrid();
-    if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->getVtkId() ))
+    vtkUnstructuredGrid* grid = const_cast<SMDS_Mesh*>( myMesh )->GetGrid();
+    if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() ))
       aVal = Round( vtkMeshQuality::TetAspectRatio( avtkCell ));
   }
   else
@@ -1028,6 +1030,11 @@ double AspectRatio3D::GetValue( long theId )
   return aVal;
 }
 
+bool AspectRatio3D::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return ( NumericalFunctor::IsApplicable( element ) && !element->IsPoly() );
+}
+
 double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
 {
   double aQuality = 0.0;
@@ -1035,12 +1042,12 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
 
   int nbNodes = P.size();
 
-  if(myCurrElement->IsQuadratic()) {
-    if(nbNodes==10) nbNodes=4; // quadratic tetrahedron
+  if( myCurrElement->IsQuadratic() ) {
+    if     (nbNodes==10) nbNodes=4; // quadratic tetrahedron
     else if(nbNodes==13) nbNodes=5; // quadratic pyramid
     else if(nbNodes==15) nbNodes=6; // quadratic pentahedron
     else if(nbNodes==20) nbNodes=8; // quadratic hexahedron
-    else if(nbNodes==27) nbNodes=8; // quadratic hexahedron
+    else if(nbNodes==27) nbNodes=8; // tri-quadratic hexahedron
     else return aQuality;
   }
 
@@ -1279,7 +1286,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
   } // switch(nbNodes)
 
   if ( nbNodes > 4 ) {
-    // avaluate aspect ratio of quadranle faces
+    // evaluate aspect ratio of quadrangle faces
     AspectRatio aspect2D;
     SMDS_VolumeTool::VolumeType type = SMDS_VolumeTool::GetType( nbNodes );
     int nbFaces = SMDS_VolumeTool::NbFaces( type );
@@ -1288,7 +1295,7 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
       if ( SMDS_VolumeTool::NbFaceNodes( type, i ) != 4 )
         continue;
       const int* pInd = SMDS_VolumeTool::GetFaceNodesIndices( type, i, true );
-      for ( int p = 0; p < 4; ++p ) // loop on nodes of a quadranle face
+      for ( int p = 0; p < 4; ++p ) // loop on nodes of a quadrangle face
         points( p + 1 ) = P( pInd[ p ] + 1 );
       aQuality = std::max( aQuality, aspect2D.GetValue( points ));
     }
@@ -1317,6 +1324,11 @@ SMDSAbs_ElementType AspectRatio3D::GetType() const
 */
 //================================================================================
 
+bool Warping::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return NumericalFunctor::IsApplicable( element ) && element->NbNodes() == 4;
+}
+
 double Warping::GetValue( const TSequenceOfXYZ& P )
 {
   if ( P.size() != 4 )
@@ -1381,6 +1393,11 @@ SMDSAbs_ElementType Warping::GetType() const
 */
 //================================================================================
 
+bool Taper::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return ( NumericalFunctor::IsApplicable( element ) && element->NbNodes() == 4 );
+}
+
 double Taper::GetValue( const TSequenceOfXYZ& P )
 {
   if ( P.size() != 4 )
@@ -1439,6 +1456,11 @@ static inline double skewAngle( const gp_XYZ& p1, const gp_XYZ& p2, const gp_XYZ
   return v1.Magnitude() < gp::Resolution() || v2.Magnitude() < gp::Resolution() ? 0. : v1.Angle( v2 );
 }
 
+bool Skew::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return ( NumericalFunctor::IsApplicable( element ) && element->NbNodes() <= 4 );
+}
+
 double Skew::GetValue( const TSequenceOfXYZ& P )
 {
   if ( P.size() != 3 && P.size() != 4 )
@@ -1553,13 +1575,36 @@ SMDSAbs_ElementType Length::GetType() const
   return SMDSAbs_Edge;
 }
 
+//================================================================================
+/*
+  Class       : Length3D
+  Description : Functor for calculating minimal length of element edge
+*/
+//================================================================================
+
+Length3D::Length3D():
+  Length2D ( SMDSAbs_Volume )
+{
+}
+
 //================================================================================
 /*
   Class       : Length2D
-  Description : Functor for calculating minimal length of edge
+  Description : Functor for calculating minimal length of element edge
 */
 //================================================================================
 
+Length2D::Length2D( SMDSAbs_ElementType type ):
+  myType ( type )
+{
+}
+
+bool Length2D::IsApplicable( const SMDS_MeshElement* element ) const
+{
+  return ( NumericalFunctor::IsApplicable( element ) &&
+           element->GetEntityType() != SMDSEntity_Polyhedra );
+}
+
 double Length2D::GetValue( const TSequenceOfXYZ& P )
 {
   double aVal = 0;
@@ -1804,7 +1849,7 @@ double Length2D::GetBadRate( double Value, int /*nbNodes*/ ) const
 
 SMDSAbs_ElementType Length2D::GetType() const
 {
-  return SMDSAbs_Face;
+  return myType;
 }
 
 Length2D::Value::Value(double theLength,long thePntId1, long thePntId2):
@@ -1826,92 +1871,96 @@ bool Length2D::Value::operator<(const Length2D::Value& x) const
 
 void Length2D::GetValues(TValues& theValues)
 {
-  TValues aValues;
-  SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-  for(; anIter->more(); ){
-    const SMDS_MeshFace* anElem = anIter->next();
+  if ( myType == SMDSAbs_Face )
+  {
+    for ( SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); anIter->more(); )
+    {
+      const SMDS_MeshFace* anElem = anIter->next();
+      if ( anElem->IsQuadratic() )
+      {
+        // use special nodes iterator
+        SMDS_NodeIteratorPtr anIter = anElem->interlacedNodesIterator();
+        long aNodeId[4] = { 0,0,0,0 };
+        gp_Pnt P[4];
 
-    if(anElem->IsQuadratic()) {
-      const SMDS_VtkFace* F =
-        dynamic_cast<const SMDS_VtkFace*>(anElem);
-      // use special nodes iterator
-      SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-      long aNodeId[4] = { 0,0,0,0 };
-      gp_Pnt P[4];
-
-      double aLength = 0;
-      const SMDS_MeshElement* aNode;
-      if(anIter->more()){
-        aNode = anIter->next();
-        const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
-        P[0] = P[1] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
-        aNodeId[0] = aNodeId[1] = aNode->GetID();
-        aLength = 0;
-      }
-      for(; anIter->more(); ){
-        const SMDS_MeshNode* N1 = static_cast<const SMDS_MeshNode*> (anIter->next());
-        P[2] = gp_Pnt(N1->X(),N1->Y(),N1->Z());
-        aNodeId[2] = N1->GetID();
-        aLength = P[1].Distance(P[2]);
-        if(!anIter->more()) break;
-        const SMDS_MeshNode* N2 = static_cast<const SMDS_MeshNode*> (anIter->next());
-        P[3] = gp_Pnt(N2->X(),N2->Y(),N2->Z());
-        aNodeId[3] = N2->GetID();
-        aLength += P[2].Distance(P[3]);
+        double aLength = 0;
+        if ( anIter->more() )
+        {
+          const SMDS_MeshNode* aNode = anIter->next();
+          P[0] = P[1] = SMESH_NodeXYZ( aNode );
+          aNodeId[0] = aNodeId[1] = aNode->GetID();
+          aLength = 0;
+        }
+        for ( ; anIter->more(); )
+        {
+          const SMDS_MeshNode* N1 = anIter->next();
+          P[2] = SMESH_NodeXYZ( N1 );
+          aNodeId[2] = N1->GetID();
+          aLength = P[1].Distance(P[2]);
+          if(!anIter->more()) break;
+          const SMDS_MeshNode* N2 = anIter->next();
+          P[3] = SMESH_NodeXYZ( N2 );
+          aNodeId[3] = N2->GetID();
+          aLength += P[2].Distance(P[3]);
+          Value aValue1(aLength,aNodeId[1],aNodeId[2]);
+          Value aValue2(aLength,aNodeId[2],aNodeId[3]);
+          P[1] = P[3];
+          aNodeId[1] = aNodeId[3];
+          theValues.insert(aValue1);
+          theValues.insert(aValue2);
+        }
+        aLength += P[2].Distance(P[0]);
         Value aValue1(aLength,aNodeId[1],aNodeId[2]);
-        Value aValue2(aLength,aNodeId[2],aNodeId[3]);
-        P[1] = P[3];
-        aNodeId[1] = aNodeId[3];
+        Value aValue2(aLength,aNodeId[2],aNodeId[0]);
         theValues.insert(aValue1);
         theValues.insert(aValue2);
       }
-      aLength += P[2].Distance(P[0]);
-      Value aValue1(aLength,aNodeId[1],aNodeId[2]);
-      Value aValue2(aLength,aNodeId[2],aNodeId[0]);
-      theValues.insert(aValue1);
-      theValues.insert(aValue2);
-    }
-    else {
-      SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
-      long aNodeId[2] = {0,0};
-      gp_Pnt P[3];
-
-      double aLength;
-      const SMDS_MeshElement* aNode;
-      if(aNodesIter->more()){
-        aNode = aNodesIter->next();
-        const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
-        P[0] = P[1] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
-        aNodeId[0] = aNodeId[1] = aNode->GetID();
-        aLength = 0;
-      }
-      for(; aNodesIter->more(); ){
-        aNode = aNodesIter->next();
-        const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode;
-        long anId = aNode->GetID();
-        
-        P[2] = gp_Pnt(aNodes->X(),aNodes->Y(),aNodes->Z());
-        
-        aLength = P[1].Distance(P[2]);
-        
-        Value aValue(aLength,aNodeId[1],anId);
-        aNodeId[1] = anId;
-        P[1] = P[2];
-        theValues.insert(aValue);
-      }
+      else {
+        SMDS_NodeIteratorPtr aNodesIter = anElem->nodeIterator();
+        long aNodeId[2] = {0,0};
+        gp_Pnt P[3];
+
+        double aLength;
+        const SMDS_MeshElement* aNode;
+        if ( aNodesIter->more())
+        {
+          aNode = aNodesIter->next();
+          P[0] = P[1] = SMESH_NodeXYZ( aNode );
+          aNodeId[0] = aNodeId[1] = aNode->GetID();
+          aLength = 0;
+        }
+        for( ; aNodesIter->more(); )
+        {
+          aNode = aNodesIter->next();
+          long anId = aNode->GetID();
+
+          P[2] = SMESH_NodeXYZ( aNode );
+
+          aLength = P[1].Distance(P[2]);
+
+          Value aValue(aLength,aNodeId[1],anId);
+          aNodeId[1] = anId;
+          P[1] = P[2];
+          theValues.insert(aValue);
+        }
 
-      aLength = P[0].Distance(P[1]);
+        aLength = P[0].Distance(P[1]);
 
-      Value aValue(aLength,aNodeId[0],aNodeId[1]);
-      theValues.insert(aValue);
+        Value aValue(aLength,aNodeId[0],aNodeId[1]);
+        theValues.insert(aValue);
+      }
     }
   }
+  else
+  {
+    // not implemented
+  }
 }
 
 //================================================================================
 /*
   Class       : Deflection2D
-  Description : Functor for calculating number of faces conneted to the edge
+  Description : computes distance between a face center and an underlying surface
 */
 //================================================================================
 
@@ -1947,8 +1996,7 @@ double Deflection2D::GetValue( const TSequenceOfXYZ& P )
       {
         gc += P(i+1);
 
-        if ( const SMDS_FacePosition* fPos = dynamic_cast<const SMDS_FacePosition*>
-             ( P.getElement()->GetNode( i )->GetPosition() ))
+        if ( SMDS_FacePositionPtr fPos = P.getElement()->GetNode( i )->GetPosition() )
         {
           uv.ChangeCoord(1) += fPos->GetUParameter();
           uv.ChangeCoord(2) += fPos->GetVParameter();
@@ -2124,59 +2172,24 @@ bool MultiConnection2D::Value::operator<(const MultiConnection2D::Value& x) cons
 void MultiConnection2D::GetValues(MValues& theValues)
 {
   if ( !myMesh ) return;
-  SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-  for(; anIter->more(); ){
-    const SMDS_MeshFace* anElem = anIter->next();
-    SMDS_ElemIteratorPtr aNodesIter;
-    if ( anElem->IsQuadratic() )
-      aNodesIter = dynamic_cast<const SMDS_VtkFace*>
-        (anElem)->interlacedNodesElemIterator();
-    else
-      aNodesIter = anElem->nodesIterator();
-    long aNodeId[3] = {0,0,0};
+  for ( SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); anIter->more(); )
+  {
+    const SMDS_MeshFace*     anElem = anIter->next();
+    SMDS_NodeIteratorPtr aNodesIter = anElem->interlacedNodesIterator();
 
-    //int aNbConnects=0;
-    const SMDS_MeshNode* aNode0;
-    const SMDS_MeshNode* aNode1;
+    const SMDS_MeshNode* aNode1 = anElem->GetNode( anElem->NbNodes() - 1 );
     const SMDS_MeshNode* aNode2;
-    if(aNodesIter->more()){
-      aNode0 = (SMDS_MeshNode*) aNodesIter->next();
-      aNode1 = aNode0;
-      const SMDS_MeshNode* aNodes = (SMDS_MeshNode*) aNode1;
-      aNodeId[0] = aNodeId[1] = aNodes->GetID();
-    }
-    for(; aNodesIter->more(); ) {
-      aNode2 = (SMDS_MeshNode*) aNodesIter->next();
-      long anId = aNode2->GetID();
-      aNodeId[2] = anId;
-
-      Value aValue(aNodeId[1],aNodeId[2]);
-      MValues::iterator aItr = theValues.find(aValue);
-      if (aItr != theValues.end()){
-        aItr->second += 1;
-        //aNbConnects = nb;
-      }
-      else {
-        theValues[aValue] = 1;
-        //aNbConnects = 1;
-      }
-      //cout << "NodeIds: "<<aNodeId[1]<<","<<aNodeId[2]<<" nbconn="<<aNbConnects<<endl;
-      aNodeId[1] = aNodeId[2];
+    for ( ; aNodesIter->more(); )
+    {
+      aNode2 = aNodesIter->next();
+
+      Value aValue ( aNode1->GetID(), aNode2->GetID() );
+      MValues::iterator aItr = theValues.insert( std::make_pair( aValue, 0 )).first;
+      aItr->second++;
       aNode1 = aNode2;
     }
-    Value aValue(aNodeId[0],aNodeId[2]);
-    MValues::iterator aItr = theValues.find(aValue);
-    if (aItr != theValues.end()) {
-      aItr->second += 1;
-      //aNbConnects = nb;
-    }
-    else {
-      theValues[aValue] = 1;
-      //aNbConnects = 1;
-    }
-    //cout << "NodeIds: "<<aNodeId[0]<<","<<aNodeId[2]<<" nbconn="<<aNbConnects<<endl;
   }
-
+  return;
 }
 
 //================================================================================
@@ -2191,7 +2204,7 @@ double BallDiameter::GetValue( long theId )
   double diameter = 0;
 
   if ( const SMDS_BallElement* ball =
-       dynamic_cast<const SMDS_BallElement*>( myMesh->FindElement( theId )))
+       myMesh->DownCast< SMDS_BallElement >( myMesh->FindElement( theId )))
   {
     diameter = ball->GetDiameter();
   }
@@ -2429,7 +2442,7 @@ void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh )
   if ( myMeshModifTracer.IsMeshModified() )
   {
     TIDSortedNodeSet nodesToCheck;
-    SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(/*idInceasingOrder=*/true);
+    SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator();
     while ( nIt->more() )
       nodesToCheck.insert( nodesToCheck.end(), nIt->next() );
 
@@ -2632,31 +2645,21 @@ inline void UpdateBorders(const FreeEdges::Border& theBorder,
 void FreeEdges::GetBoreders(TBorders& theBorders)
 {
   TBorders aRegistry;
-  SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-  for(; anIter->more(); ){
+  for ( SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); anIter->more(); )
+  {
     const SMDS_MeshFace* anElem = anIter->next();
     long anElemId = anElem->GetID();
-    SMDS_ElemIteratorPtr aNodesIter;
-    if ( anElem->IsQuadratic() )
-      aNodesIter = static_cast<const SMDS_VtkFace*>(anElem)->
-        interlacedNodesElemIterator();
-    else
-      aNodesIter = anElem->nodesIterator();
+    SMDS_NodeIteratorPtr aNodesIter = anElem->interlacedNodesIterator();
+    if ( !aNodesIter->more() ) continue;
     long aNodeId[2] = {0,0};
-    const SMDS_MeshElement* aNode;
-    if(aNodesIter->more()){
-      aNode = aNodesIter->next();
-      aNodeId[0] = aNodeId[1] = aNode->GetID();
-    }
-    for(; aNodesIter->more(); ){
-      aNode = aNodesIter->next();
-      long anId = aNode->GetID();
-      Border aBorder(anElemId,aNodeId[1],anId);
-      aNodeId[1] = anId;
-      UpdateBorders(aBorder,aRegistry,theBorders);
+    aNodeId[0] = anElem->GetNode( anElem->NbNodes()-1 )->GetID();
+    for ( ; aNodesIter->more(); )
+    {
+      aNodeId[1] = aNodesIter->next()->GetID();
+      Border aBorder( anElemId, aNodeId[0], aNodeId[1] );
+      UpdateBorders( aBorder, aRegistry, theBorders );
+      aNodeId[0] = aNodeId[1];
     }
-    Border aBorder(anElemId,aNodeId[0],aNodeId[1]);
-    UpdateBorders(aBorder,aRegistry,theBorders);
   }
 }
 
@@ -3112,7 +3115,7 @@ bool ConnectedElements::IsSatisfy( long theElementId )
       {
         // keep elements of myType
         const SMDS_MeshElement* element = eIt->next();
-        if ( element->GetType() == myType )
+        if ( myType == SMDSAbs_All || element->GetType() == myType )
           myOkIDs.insert( myOkIDs.end(), element->GetID() );
 
         // enqueue nodes of the element
@@ -3658,9 +3661,10 @@ void Filter::SetPredicate( PredicatePtr thePredicate )
   myPredicate = thePredicate;
 }
 
-void Filter::GetElementsId( const SMDS_Mesh* theMesh,
-                            PredicatePtr     thePredicate,
-                            TIdSequence&     theSequence )
+void Filter::GetElementsId( const SMDS_Mesh*     theMesh,
+                            PredicatePtr         thePredicate,
+                            TIdSequence&         theSequence,
+                            SMDS_ElemIteratorPtr theElements )
 {
   theSequence.clear();
 
@@ -3669,21 +3673,28 @@ void Filter::GetElementsId( const SMDS_Mesh* theMesh,
 
   thePredicate->SetMesh( theMesh );
 
-  SMDS_ElemIteratorPtr elemIt = theMesh->elementsIterator( thePredicate->GetType() );
-  if ( elemIt ) {
-    while ( elemIt->more() ) {
-      const SMDS_MeshElement* anElem = elemIt->next();
-      long anId = anElem->GetID();
-      if ( thePredicate->IsSatisfy( anId ) )
-        theSequence.push_back( anId );
+  if ( !theElements )
+    theElements = theMesh->elementsIterator( thePredicate->GetType() );
+
+  if ( theElements ) {
+    while ( theElements->more() ) {
+      const SMDS_MeshElement* anElem = theElements->next();
+      if ( thePredicate->GetType() == SMDSAbs_All ||
+           thePredicate->GetType() == anElem->GetType() )
+      {
+        long anId = anElem->GetID();
+        if ( thePredicate->IsSatisfy( anId ) )
+          theSequence.push_back( anId );
+      }
     }
   }
 }
 
 void Filter::GetElementsId( const SMDS_Mesh*     theMesh,
-                            Filter::TIdSequence& theSequence )
+                            Filter::TIdSequence& theSequence,
+                            SMDS_ElemIteratorPtr theElements )
 {
-  GetElementsId(theMesh,myPredicate,theSequence);
+  GetElementsId(theMesh,myPredicate,theSequence,theElements);
 }
 
 /*
@@ -4008,24 +4019,20 @@ void ManifoldPart::expandBoundary
 void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
                                    ManifoldPart::TVectorOfFacePtr& theFaces ) const
 {
-  std::set<SMDS_MeshCell *> aSetOfFaces;
+
   // take all faces that shared first node
-  SMDS_ElemIteratorPtr anItr = theLink.myNode1->facesIterator();
-  for ( ; anItr->more(); )
-  {
-    SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
-    if ( !aFace )
-      continue;
-    aSetOfFaces.insert( aFace );
-  }
+  SMDS_ElemIteratorPtr anItr = theLink.myNode1->GetInverseElementIterator( SMDSAbs_Face );
+  SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > faces( anItr ), facesEnd;
+  std::set<const SMDS_MeshElement *> aSetOfFaces( faces, facesEnd );
+
   // take all faces that shared second node
-  anItr = theLink.myNode2->facesIterator();
+  anItr = theLink.myNode2->GetInverseElementIterator( SMDSAbs_Face );
   // find the common part of two sets
   for ( ; anItr->more(); )
   {
-    SMDS_MeshFace* aFace = (SMDS_MeshFace*)anItr->next();
-    if ( aSetOfFaces.count( aFace ) )
-      theFaces.push_back( aFace );
+    const SMDS_MeshElement* aFace = anItr->next();
+    if ( aSetOfFaces.count( aFace ))
+      theFaces.push_back( (SMDS_MeshFace*) aFace );
   }
 }
 
@@ -4115,8 +4122,10 @@ SMDSAbs_ElementType ElementsOnSurface::GetType() const
 void ElementsOnSurface::SetTolerance( const double theToler )
 {
   if ( myToler != theToler )
-    myIds.Clear();
-  myToler = theToler;
+  {
+    myToler = theToler;
+    process();
+  }
 }
 
 double ElementsOnSurface::GetTolerance() const
@@ -4498,6 +4507,12 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshElement* elem)
   return isSatisfy;
 }
 
+//================================================================================
+/*!
+ * \brief Check and optionally return a satisfying shape
+ */
+//================================================================================
+
 bool ElementsOnShape::IsSatisfy (const SMDS_MeshNode* node,
                                  TopoDS_Shape*        okShape)
 {
@@ -4634,6 +4649,7 @@ ElementsOnShape::Classifier::~Classifier()
 
 bool ElementsOnShape::Classifier::isOutOfSolid (const gp_Pnt& p)
 {
+  if ( isOutOfBox( p )) return true;
   mySolidClfr->Perform( p, myTol );
   return ( mySolidClfr->State() != TopAbs_IN && mySolidClfr->State() != TopAbs_ON );
 }
@@ -4645,6 +4661,7 @@ bool ElementsOnShape::Classifier::isOutOfBox (const gp_Pnt& p)
 
 bool ElementsOnShape::Classifier::isOutOfFace  (const gp_Pnt& p)
 {
+  if ( isOutOfBox( p )) return true;
   myProjFace.Perform( p );
   if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol )
   {
@@ -4661,6 +4678,7 @@ bool ElementsOnShape::Classifier::isOutOfFace  (const gp_Pnt& p)
 
 bool ElementsOnShape::Classifier::isOutOfEdge  (const gp_Pnt& p)
 {
+  if ( isOutOfBox( p )) return true;
   myProjEdge.Perform( p );
   return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol );
 }
@@ -4933,7 +4951,7 @@ bool BelongToGeom::IsSatisfy (long theId)
   {
     if ( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ))
     {
-      if ( anElem->GetType() == myType )
+      if ( myType == SMDSAbs_All || anElem->GetType() == myType )
       {
         if ( anElem->getshapeId() < 1 )
           return myElementsOnShapePtr->IsSatisfy(theId);
@@ -5073,7 +5091,8 @@ bool LyingOnGeom::IsSatisfy( long theId )
   if ( mySubShapesIDs.Contains( elem->getshapeId() ))
     return true;
 
-  if ( elem->GetType() != SMDSAbs_Node && elem->GetType() == myType )
+  if (( elem->GetType() != SMDSAbs_Node ) &&
+      ( myType == SMDSAbs_All || elem->GetType() == myType ))
   {
     SMDS_ElemIteratorPtr nodeItr = elem->nodesIterator();
     while ( nodeItr->more() )