Salome HOME
Fix for the "0021861: EDF 2226 : Documentation of numeric functor option in split...
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index 072aea8e195915201162f2d336b484262ecb5075..6b400350d09daae940b87994fc36ecec6be6ac76 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  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
 
 #include "SMESH_ControlsDef.hxx"
 
-#include <set>
-#include <limits>
+#include "SMDS_BallElement.hxx"
+#include "SMDS_Iterator.hxx"
+#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_Mesh.hxx"
+#include "SMESH_OctreeNode.hxx"
 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepClass_FaceClassifier.hxx>
 #include <BRep_Tool.hxx>
-
-#include <TopAbs.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Iterator.hxx>
-
 #include <Geom_CylindricalSurface.hxx>
 #include <Geom_Plane.hxx>
 #include <Geom_Surface.hxx>
-
 #include <Precision.hxx>
 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
 #include <TColStd_MapOfInteger.hxx>
 #include <TColStd_SequenceOfAsciiString.hxx>
 #include <TColgp_Array1OfXYZ.hxx>
-
+#include <TopAbs.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
 #include <gp_Ax3.hxx>
 #include <gp_Cylinder.hxx>
 #include <gp_Dir.hxx>
 #include <gp_Vec.hxx>
 #include <gp_XYZ.hxx>
 
-#include "SMDS_Mesh.hxx"
-#include "SMDS_Iterator.hxx"
-#include "SMDS_MeshElement.hxx"
-#include "SMDS_MeshNode.hxx"
-#include "SMDS_VolumeTool.hxx"
-#include "SMDS_QuadraticFaceOfNodes.hxx"
-#include "SMDS_QuadraticEdge.hxx"
+#include <vtkMeshQuality.h>
 
-#include "SMESHDS_Mesh.hxx"
-#include "SMESHDS_GroupBase.hxx"
+#include <set>
+#include <limits>
 
-#include <vtkMeshQuality.h>
 
 /*
                             AUXILIARY METHODS
@@ -431,59 +429,56 @@ SMDSAbs_ElementType Volume::GetType() const
   Class       : MaxElementLength2D
   Description : Functor calculating maximum length of 2D element
 */
+double MaxElementLength2D::GetValue( const TSequenceOfXYZ& P )
+{
+  if(P.size() == 0)
+    return 0.;
+  double aVal = 0;
+  int len = P.size();
+  if( len == 3 ) { // triangles
+    double L1 = getDistance(P( 1 ),P( 2 ));
+    double L2 = getDistance(P( 2 ),P( 3 ));
+    double L3 = getDistance(P( 3 ),P( 1 ));
+    aVal = Max(L1,Max(L2,L3));
+  }
+  else if( len == 4 ) { // quadrangles
+    double L1 = getDistance(P( 1 ),P( 2 ));
+    double L2 = getDistance(P( 2 ),P( 3 ));
+    double L3 = getDistance(P( 3 ),P( 4 ));
+    double L4 = getDistance(P( 4 ),P( 1 ));
+    double D1 = getDistance(P( 1 ),P( 3 ));
+    double D2 = getDistance(P( 2 ),P( 4 ));
+    aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
+  }
+  else if( len == 6 ) { // quadratic triangles
+    double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
+    double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
+    double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
+    aVal = Max(L1,Max(L2,L3));
+  }
+  else if( len == 8 || len == 9 ) { // quadratic quadrangles
+    double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
+    double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
+    double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
+    double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
+    double D1 = getDistance(P( 1 ),P( 5 ));
+    double D2 = getDistance(P( 3 ),P( 7 ));
+    aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
+  }
+
+  if( myPrecision >= 0 )
+  {
+    double prec = pow( 10., (double)myPrecision );
+    aVal = floor( aVal * prec + 0.5 ) / prec;
+  }
+  return aVal;
+}
 
 double MaxElementLength2D::GetValue( long theElementId )
 {
   TSequenceOfXYZ P;
-  if( GetPoints( theElementId, P ) ) {
-    double aVal = 0;
-    const SMDS_MeshElement* aElem = myMesh->FindElement( theElementId );
-    SMDSAbs_ElementType aType = aElem->GetType();
-    int len = P.size();
-    switch( aType ) {
-    case SMDSAbs_Face:
-      if( len == 3 ) { // triangles
-        double L1 = getDistance(P( 1 ),P( 2 ));
-        double L2 = getDistance(P( 2 ),P( 3 ));
-        double L3 = getDistance(P( 3 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
-        break;
-      }
-      else if( len == 4 ) { // quadrangles
-        double L1 = getDistance(P( 1 ),P( 2 ));
-        double L2 = getDistance(P( 2 ),P( 3 ));
-        double L3 = getDistance(P( 3 ),P( 4 ));
-        double L4 = getDistance(P( 4 ),P( 1 ));
-        double D1 = getDistance(P( 1 ),P( 3 ));
-        double D2 = getDistance(P( 2 ),P( 4 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
-        break;
-      }
-      else if( len == 6 ) { // quadratic triangles
-        double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
-        double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
-        double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 1 ));
-        aVal = Max(L1,Max(L2,L3));
-        break;
-      }
-      else if( len == 8 || len == 9 ) { // quadratic quadrangles
-        double L1 = getDistance(P( 1 ),P( 2 )) + getDistance(P( 2 ),P( 3 ));
-        double L2 = getDistance(P( 3 ),P( 4 )) + getDistance(P( 4 ),P( 5 ));
-        double L3 = getDistance(P( 5 ),P( 6 )) + getDistance(P( 6 ),P( 7 ));
-        double L4 = getDistance(P( 7 ),P( 8 )) + getDistance(P( 8 ),P( 1 ));
-        double D1 = getDistance(P( 1 ),P( 5 ));
-        double D2 = getDistance(P( 3 ),P( 7 ));
-        aVal = Max(Max(Max(L1,L2),Max(L3,L4)),Max(D1,D2));
-        break;
-      }
-    }
-
-    if( myPrecision >= 0 )
-    {
-      double prec = pow( 10., (double)myPrecision );
-      aVal = floor( aVal * prec + 0.5 ) / prec;
-    }
-    return aVal;
+  if( GetPoints( theElementId, P ) && myMesh->FindElement( theElementId )->GetType() == SMDSAbs_Face) {
+    GetValue(P);
   }
   return 0.;
 }
@@ -693,7 +688,7 @@ double MinimumAngle::GetValue( const TSequenceOfXYZ& P )
     aMin = Min(aMin,A0);
   }
 
-  return aMin * 180.0 / PI;
+  return aMin * 180.0 / M_PI;
 }
 
 double MinimumAngle::GetBadRate( double Value, int nbNodes ) const
@@ -713,6 +708,26 @@ SMDSAbs_ElementType MinimumAngle::GetType() const
   Class       : AspectRatio
   Description : Functor for calculating aspect ratio
 */
+double AspectRatio::GetValue( long theId )
+{
+  double aVal = 0;
+  myCurrElement = myMesh->FindElement( theId );
+  if ( myCurrElement && myCurrElement->GetVtkType() == VTK_QUAD )
+  {
+    // issue 21723
+    vtkUnstructuredGrid* grid = SMDS_Mesh::_meshList[myCurrElement->getMeshId()]->getGrid();
+    if ( vtkCell* avtkCell = grid->GetCell( myCurrElement->getVtkId() ))
+      aVal = Round( vtkMeshQuality::QuadAspectRatio( avtkCell ));
+  }
+  else
+  {
+    TSequenceOfXYZ P;
+    if ( GetPoints( myCurrElement, P ))
+      aVal = Round( GetValue( P ));
+  }
+  return aVal;
+}
+
 double AspectRatio::GetValue( const TSequenceOfXYZ& P )
 {
   // According to "Mesh quality control" by Nadir Bouhamau referring to
@@ -1278,12 +1293,12 @@ double Warping::ComputeA( const gp_XYZ& thePnt1,
   gp_XYZ N  = GI.Crossed( GJ );
 
   if ( N.Modulus() < gp::Resolution() )
-    return PI / 2;
+    return M_PI / 2;
 
   N.Normalize();
 
   double H = ( thePnt2 - theG ).Dot( N );
-  return asin( fabs( H / L ) ) * 180. / PI;
+  return asin( fabs( H / L ) ) * 180. / M_PI;
 }
 
 double Warping::GetBadRate( double Value, int /*nbNodes*/ ) const
@@ -1362,14 +1377,14 @@ double Skew::GetValue( const TSequenceOfXYZ& P )
     return 0.;
 
   // Compute skew
-  static double PI2 = PI / 2.;
+  static double PI2 = M_PI / 2.;
   if ( P.size() == 3 )
   {
     double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) );
     double A1 = fabs( PI2 - skewAngle( P( 1 ), P( 2 ), P( 3 ) ) );
     double A2 = fabs( PI2 - skewAngle( P( 2 ), P( 3 ), P( 1 ) ) );
 
-    return Max( A0, Max( A1, A2 ) ) * 180. / PI;
+    return Max( A0, Max( A1, A2 ) ) * 180. / M_PI;
   }
   else
   {
@@ -1386,7 +1401,7 @@ double Skew::GetValue( const TSequenceOfXYZ& P )
     if ( A < Precision::Angular() )
       return 0.;
 
-    return A * 180. / PI;
+    return A * 180. / M_PI;
   }
 }
 
@@ -1944,6 +1959,34 @@ void MultiConnection2D::GetValues(MValues& theValues){
 
 }
 
+/*
+  Class       : BallDiameter
+  Description : Functor returning diameter of a ball element
+*/
+double BallDiameter::GetValue( long theId )
+{
+  double diameter = 0;
+
+  if ( const SMDS_BallElement* ball =
+       dynamic_cast<const SMDS_BallElement*>( myMesh->FindElement( theId )))
+  {
+    diameter = ball->GetDiameter();
+  }
+  return diameter;
+}
+
+double BallDiameter::GetBadRate( double Value, int /*nbNodes*/ ) const
+{
+  // meaningless as it is not a quality control functor
+  return Value;
+}
+
+SMDSAbs_ElementType BallDiameter::GetType() const
+{
+  return SMDSAbs_Ball;
+}
+
+
 /*
                             PREDICATES
 */
@@ -2024,10 +2067,11 @@ bool BareBorderFace::IsSatisfy(long theElementId )
         }
         if ( !isShared )
         {
-          myLinkNodes.resize( 2 + face->IsQuadratic());
+          const int iQuad = face->IsQuadratic();
+          myLinkNodes.resize( 2 + iQuad);
           myLinkNodes[0] = n1;
           myLinkNodes[1] = n2;
-          if ( face->IsQuadratic() )
+          if ( iQuad )
             myLinkNodes[2] = face->GetNode( i+nbN );
           ok = !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, /*noMedium=*/false);
         }
@@ -2090,6 +2134,106 @@ bool OverConstrainedFace::IsSatisfy(long theElementId )
   return false;
 }
 
+/*
+  Class       : CoincidentNodes
+  Description : Predicate of Coincident nodes
+*/
+
+CoincidentNodes::CoincidentNodes()
+{
+  myToler = 1e-5;
+}
+
+bool CoincidentNodes::IsSatisfy( long theElementId )
+{
+  return myCoincidentIDs.Contains( theElementId );
+}
+
+SMDSAbs_ElementType CoincidentNodes::GetType() const
+{
+  return SMDSAbs_Node;
+}
+
+void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh )
+{
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified() )
+  {
+    TIDSortedNodeSet nodesToCheck;
+    SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(/*idInceasingOrder=*/true);
+    while ( nIt->more() )
+      nodesToCheck.insert( nodesToCheck.end(), nIt->next() );
+
+    list< list< const SMDS_MeshNode*> > nodeGroups;
+    SMESH_OctreeNode::FindCoincidentNodes ( nodesToCheck, &nodeGroups, myToler );
+
+    myCoincidentIDs.Clear();
+    list< list< const SMDS_MeshNode*> >::iterator groupIt = nodeGroups.begin();
+    for ( ; groupIt != nodeGroups.end(); ++groupIt )
+    {
+      list< const SMDS_MeshNode*>& coincNodes = *groupIt;
+      list< const SMDS_MeshNode*>::iterator n = coincNodes.begin();
+      for ( ; n != coincNodes.end(); ++n )
+        myCoincidentIDs.Add( (*n)->GetID() );
+    }
+  }
+}
+
+/*
+  Class       : CoincidentElements
+  Description : Predicate of Coincident Elements
+  Note        : This class is suitable only for visualization of Coincident Elements
+*/
+
+CoincidentElements::CoincidentElements()
+{
+  myMesh = 0;
+}
+
+void CoincidentElements::SetMesh( const SMDS_Mesh* theMesh )
+{
+  myMesh = theMesh;
+}
+
+bool CoincidentElements::IsSatisfy( long theElementId )
+{
+  if ( !myMesh ) return false;
+
+  if ( const SMDS_MeshElement* e = myMesh->FindElement( theElementId ))
+  {
+    if ( e->GetType() != GetType() ) return false;
+    set< const SMDS_MeshNode* > elemNodes( e->begin_nodes(), e->end_nodes() );
+    const int nbNodes = e->NbNodes();
+    SMDS_ElemIteratorPtr invIt = (*elemNodes.begin())->GetInverseElementIterator( GetType() );
+    while ( invIt->more() )
+    {
+      const SMDS_MeshElement* e2 = invIt->next();
+      if ( e2 == e || e2->NbNodes() != nbNodes ) continue;
+
+      bool sameNodes = true;
+      for ( size_t i = 0; i < elemNodes.size() && sameNodes; ++i )
+        sameNodes = ( elemNodes.count( e2->GetNode( i )));
+      if ( sameNodes )
+        return true;
+    }
+  }
+  return false;
+}
+
+SMDSAbs_ElementType CoincidentElements1D::GetType() const
+{
+  return SMDSAbs_Edge;
+}
+SMDSAbs_ElementType CoincidentElements2D::GetType() const
+{
+  return SMDSAbs_Face;
+}
+SMDSAbs_ElementType CoincidentElements3D::GetType() const
+{
+  return SMDSAbs_Volume;
+}
+
+
 /*
   Class       : FreeBorders
   Description : Predicate for free borders
@@ -2498,43 +2642,7 @@ bool ElemGeomType::IsSatisfy( long theId )
   const SMDSAbs_ElementType anElemType = anElem->GetType();
   if ( myType != SMDSAbs_All && anElemType != myType )
     return false;
-  const int aNbNode = anElem->NbNodes();
-  bool isOk = false;
-  switch( anElemType )
-  {
-  case SMDSAbs_Node:
-    isOk = (myGeomType == SMDSGeom_POINT);
-    break;
-
-  case SMDSAbs_Edge:
-    isOk = (myGeomType == SMDSGeom_EDGE);
-    break;
-
-  case SMDSAbs_Face:
-    if ( myGeomType == SMDSGeom_TRIANGLE )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 6 : aNbNode == 3));
-    else if ( myGeomType == SMDSGeom_QUADRANGLE )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? ( aNbNode == 8 || aNbNode == 9 ) : aNbNode == 4));
-    else if ( myGeomType == SMDSGeom_POLYGON )
-      isOk = anElem->IsPoly();
-    break;
-
-  case SMDSAbs_Volume:
-    if ( myGeomType == SMDSGeom_TETRA )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 10 : aNbNode == 4));
-    else if ( myGeomType == SMDSGeom_PYRAMID )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 13 : aNbNode == 5));
-    else if ( myGeomType == SMDSGeom_PENTA )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? aNbNode == 15 : aNbNode == 6));
-    else if ( myGeomType == SMDSGeom_HEXA )
-      isOk = (!anElem->IsPoly() && (anElem->IsQuadratic() ? ( aNbNode == 20 || aNbNode == 27 ): aNbNode == 8));
-    else if ( myGeomType == SMDSGeom_HEXAGONAL_PRISM )
-      isOk = (anElem->GetEntityType() == SMDSEntity_Hexagonal_Prism );
-     else if ( myGeomType == SMDSGeom_POLYHEDRA )
-      isOk = anElem->IsPoly();
-    break;
-    default: break;
-  }
+  bool isOk = ( anElem->GetGeomType() == myGeomType );
   return isOk;
 }
 
@@ -2565,59 +2673,72 @@ SMDSAbs_GeometryType ElemGeomType::GetGeomType() const
 //================================================================================
 
 CoplanarFaces::CoplanarFaces()
-  : myMesh(0), myFaceID(0), myToler(0)
+  : myFaceID(0), myToler(0)
 {
 }
-bool CoplanarFaces::IsSatisfy( long theElementId )
+void CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh )
 {
-  if ( myCoplanarIDs.empty() )
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified() )
   {
     // Build a set of coplanar face ids
 
-    if ( !myMesh || !myFaceID || !myToler )
-      return false;
+    myCoplanarIDs.clear();
+
+    if ( !myMeshModifTracer.GetMesh() || !myFaceID || !myToler )
+      return;
 
-    const SMDS_MeshElement* face = myMesh->FindElement( myFaceID );
+    const SMDS_MeshElement* face = myMeshModifTracer.GetMesh()->FindElement( myFaceID );
     if ( !face || face->GetType() != SMDSAbs_Face )
-      return false;
+      return;
 
     bool normOK;
     gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
     if (!normOK)
-      return false;
+      return;
 
-    const double radianTol = myToler * PI180;
-    typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt;
-    std::set<const SMDS_MeshElement*> checkedFaces, checkedNodes;
-    std::list<const SMDS_MeshElement*> faceQueue( 1, face );
+    const double radianTol = myToler * M_PI / 180.;
+    std::set< SMESH_TLink > checkedLinks;
+
+    std::list< pair< const SMDS_MeshElement*, gp_Vec > > faceQueue;
+    faceQueue.push_back( make_pair( face, myNorm ));
     while ( !faceQueue.empty() )
     {
-      face = faceQueue.front();
-      if ( checkedFaces.insert( face ).second )
+      face   = faceQueue.front().first;
+      myNorm = faceQueue.front().second;
+      faceQueue.pop_front();
+
+      for ( int i = 0, nbN = face->NbCornerNodes(); i < nbN; ++i )
       {
-        gp_Vec norm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
-        if (!normOK || myNorm.Angle( norm ) <= radianTol)
+        const SMDS_MeshNode*  n1 = face->GetNode( i );
+        const SMDS_MeshNode*  n2 = face->GetNode(( i+1 )%nbN);
+        if ( !checkedLinks.insert( SMESH_TLink( n1, n2 )).second )
+          continue;
+        SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator(SMDSAbs_Face);
+        while ( fIt->more() )
         {
-          myCoplanarIDs.insert( face->GetID() );
-          std::set<const SMDS_MeshElement*> neighborFaces;
-          for ( int i = 0; i < face->NbCornerNodes(); ++i )
+          const SMDS_MeshElement* f = fIt->next();
+          if ( f->GetNodeIndex( n2 ) > -1 )
           {
-            const SMDS_MeshNode* n = face->GetNode( i );
-            if ( checkedNodes.insert( n ).second )
-              neighborFaces.insert( TFaceIt( n->GetInverseElementIterator(SMDSAbs_Face)),
-                                    TFaceIt());
+            gp_Vec norm = getNormale( static_cast<const SMDS_MeshFace*>(f), &normOK );
+            if (!normOK || myNorm.Angle( norm ) <= radianTol)
+            {
+              myCoplanarIDs.insert( f->GetID() );
+              faceQueue.push_back( make_pair( f, norm ));
+            }
           }
-          faceQueue.insert( faceQueue.end(), neighborFaces.begin(), neighborFaces.end() );
         }
       }
-      faceQueue.pop_front();
     }
   }
+}
+bool CoplanarFaces::IsSatisfy( long theElementId )
+{
   return myCoplanarIDs.count( theElementId );
 }
 
 /*
 *Class       : RangeOfIds
+ *Class       : RangeOfIds
   *Description : Predicate for Range of Ids.
   *              Range may be specified with two ways.
   *              1. Using AddToRange method
@@ -3027,26 +3148,9 @@ void Filter::SetPredicate( PredicatePtr thePredicate )
   myPredicate = thePredicate;
 }
 
-template<class TElement, class TIterator, class TPredicate>
-inline void FillSequence(const TIterator& theIterator,
-                         TPredicate& thePredicate,
-                         Filter::TIdSequence& theSequence)
-{
-  if ( theIterator ) {
-    while( theIterator->more() ) {
-      TElement anElem = theIterator->next();
-      long anId = anElem->GetID();
-      if ( thePredicate->IsSatisfy( anId ) )
-        theSequence.push_back( anId );
-    }
-  }
-}
-
-void
-Filter::
-GetElementsId( const SMDS_Mesh* theMesh,
-               PredicatePtr thePredicate,
-               TIdSequence& theSequence )
+void Filter::GetElementsId( const SMDS_Mesh* theMesh,
+                            PredicatePtr     thePredicate,
+                            TIdSequence&     theSequence )
 {
   theSequence.clear();
 
@@ -3055,31 +3159,19 @@ GetElementsId( const SMDS_Mesh* theMesh,
 
   thePredicate->SetMesh( theMesh );
 
-  SMDSAbs_ElementType aType = thePredicate->GetType();
-  switch(aType){
-  case SMDSAbs_Node:
-    FillSequence<const SMDS_MeshNode*>(theMesh->nodesIterator(),thePredicate,theSequence);
-    break;
-  case SMDSAbs_Edge:
-    FillSequence<const SMDS_MeshElement*>(theMesh->edgesIterator(),thePredicate,theSequence);
-    break;
-  case SMDSAbs_Face:
-    FillSequence<const SMDS_MeshElement*>(theMesh->facesIterator(),thePredicate,theSequence);
-    break;
-  case SMDSAbs_Volume:
-    FillSequence<const SMDS_MeshElement*>(theMesh->volumesIterator(),thePredicate,theSequence);
-    break;
-  case SMDSAbs_All:
-    FillSequence<const SMDS_MeshElement*>(theMesh->edgesIterator(),thePredicate,theSequence);
-    FillSequence<const SMDS_MeshElement*>(theMesh->facesIterator(),thePredicate,theSequence);
-    FillSequence<const SMDS_MeshElement*>(theMesh->volumesIterator(),thePredicate,theSequence);
-    break;
+  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 );
+    }
   }
 }
 
-void
-Filter::GetElementsId( const SMDS_Mesh* theMesh,
-                       Filter::TIdSequence& theSequence )
+void Filter::GetElementsId( const SMDS_Mesh*     theMesh,
+                            Filter::TIdSequence& theSequence )
 {
   GetElementsId(theMesh,myPredicate,theSequence);
 }
@@ -3434,7 +3526,6 @@ void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
 
 ElementsOnSurface::ElementsOnSurface()
 {
-  myMesh = 0;
   myIds.Clear();
   myType = SMDSAbs_All;
   mySurf.Nullify();
@@ -3444,15 +3535,13 @@ ElementsOnSurface::ElementsOnSurface()
 
 ElementsOnSurface::~ElementsOnSurface()
 {
-  myMesh = 0;
 }
 
 void ElementsOnSurface::SetMesh( const SMDS_Mesh* theMesh )
 {
-  if ( myMesh == theMesh )
-    return;
-  myMesh = theMesh;
-  process();
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified())
+    process();
 }
 
 bool ElementsOnSurface::IsSatisfy( long theElementId )
@@ -3507,32 +3596,14 @@ void ElementsOnSurface::process()
   if ( mySurf.IsNull() )
     return;
 
-  if ( myMesh == 0 )
+  if ( !myMeshModifTracer.GetMesh() )
     return;
 
-  if ( myType == SMDSAbs_Face || myType == SMDSAbs_All )
-  {
-    myIds.ReSize( myMesh->NbFaces() );
-    SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-    for(; anIter->more(); )
-      process( anIter->next() );
-  }
+  myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ));
 
-  if ( myType == SMDSAbs_Edge || myType == SMDSAbs_All )
-  {
-    myIds.ReSize( myIds.Extent() + myMesh->NbEdges() );
-    SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
-    for(; anIter->more(); )
-      process( anIter->next() );
-  }
-
-  if ( myType == SMDSAbs_Node )
-  {
-    myIds.ReSize( myMesh->NbNodes() );
-    SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
-    for(; anIter->more(); )
-      process( anIter->next() );
-  }
+  SMDS_ElemIteratorPtr anIter = myMeshModifTracer.GetMesh()->elementsIterator( myType );
+  for(; anIter->more(); )
+    process( anIter->next() );
 }
 
 void ElementsOnSurface::process( const SMDS_MeshElement* theElemPtr )
@@ -3590,7 +3661,7 @@ bool ElementsOnSurface::isOnSurface( const SMDS_MeshNode* theNode )
 */
 
 ElementsOnShape::ElementsOnShape()
-  : myMesh(0),
+  : //myMesh(0),
     myType(SMDSAbs_All),
     myToler(Precision::Confusion()),
     myAllNodesFlag(false)
@@ -3604,10 +3675,9 @@ ElementsOnShape::~ElementsOnShape()
 
 void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
 {
-  if (myMesh != theMesh) {
-    myMesh = theMesh;
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified())
     SetShape(myShape, myType);
-  }
 }
 
 bool ElementsOnShape::IsSatisfy (long theElementId)
@@ -3648,28 +3718,11 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myShape = theShape;
   myIds.Clear();
 
-  if (myMesh == 0) return;
+  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
+  
+  if ( !myMesh ) return;
 
-  switch (myType)
-  {
-  case SMDSAbs_All:
-    myIds.ReSize(myMesh->NbEdges() + myMesh->NbFaces() + myMesh->NbVolumes());
-    break;
-  case SMDSAbs_Node:
-    myIds.ReSize(myMesh->NbNodes());
-    break;
-  case SMDSAbs_Edge:
-    myIds.ReSize(myMesh->NbEdges());
-    break;
-  case SMDSAbs_Face:
-    myIds.ReSize(myMesh->NbFaces());
-    break;
-  case SMDSAbs_Volume:
-    myIds.ReSize(myMesh->NbVolumes());
-    break;
-  default:
-    break;
-  }
+  myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ));
 
   myShapesMap.Clear();
   addShape(myShape);
@@ -3677,7 +3730,7 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
 
 void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
 {
-  if (theShape.IsNull() || myMesh == 0)
+  if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
     return;
 
   if (!myShapesMap.Add(theShape)) return;
@@ -3738,39 +3791,13 @@ void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
 
 void ElementsOnShape::process()
 {
+  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
   if (myShape.IsNull() || myMesh == 0)
     return;
 
-  if (myType == SMDSAbs_Node)
-  {
-    SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
-    while (anIter->more())
-      process(anIter->next());
-  }
-  else
-  {
-    if (myType == SMDSAbs_Edge || myType == SMDSAbs_All)
-    {
-      SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
-      while (anIter->more())
-        process(anIter->next());
-    }
-
-    if (myType == SMDSAbs_Face || myType == SMDSAbs_All)
-    {
-      SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-      while (anIter->more()) {
-        process(anIter->next());
-      }
-    }
-
-    if (myType == SMDSAbs_Volume || myType == SMDSAbs_All)
-    {
-      SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
-      while (anIter->more())
-        process(anIter->next());
-    }
-  }
+  SMDS_ElemIteratorPtr anIter = myMesh->elementsIterator(myType);
+  while (anIter->more())
+    process(anIter->next());
 }
 
 void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
@@ -3785,9 +3812,8 @@ void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
 
   while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
   {
-    SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
-    gp_Pnt aPnt (aNode->X(), aNode->Y(), aNode->Z());
-    centerXYZ += aPnt.XYZ();
+    SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
+    centerXYZ += aPnt;
 
     switch (myCurShapeType)
     {
@@ -3820,7 +3846,7 @@ void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
       break;
     case TopAbs_VERTEX:
       {
-        isSatisfy = (aPnt.Distance(myCurPnt) <= myToler);
+        isSatisfy = (myCurPnt.Distance(aPnt) <= myToler);
       }
       break;
     default:
@@ -3896,3 +3922,24 @@ TSequenceOfXYZ::size_type TSequenceOfXYZ::size() const
 {
   return myArray.size();
 }
+
+TMeshModifTracer::TMeshModifTracer():
+  myMeshModifTime(0), myMesh(0)
+{
+}
+void TMeshModifTracer::SetMesh( const SMDS_Mesh* theMesh )
+{
+  if ( theMesh != myMesh )
+    myMeshModifTime = 0;
+  myMesh = theMesh;
+}
+bool TMeshModifTracer::IsMeshModified()
+{
+  bool modified = false;
+  if ( myMesh )
+  {
+    modified = ( myMeshModifTime != myMesh->GetMTime() );
+    myMeshModifTime = myMesh->GetMTime();
+  }
+  return modified;
+}