Salome HOME
52459: Viscous layers are not normal to the surface.
[modules/smesh.git] / src / SMESH_I / SMESH_Filter_i.cxx
index ac5273396741e51615d7d3a25b0a1526ce7df638..d81f7f667faa5ea81bd417a9acafd1ef577fb002 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  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
@@ -6,7 +6,7 @@
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,6 +18,7 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
 //  File   : SMESH_Filter_i.cxx
 #include "SMDS_MeshNode.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESH_Gen_i.hxx"
+#include "SMESH_Group_i.hxx"
 #include "SMESH_PythonDump.hxx"
 
 #include <SALOMEDS_wrap.hxx>
+#include <GEOM_wrap.hxx>
 
 #include <BRep_Tool.hxx>
 #include <Geom_CylindricalSurface.hxx>
 #include <TColStd_ListOfReal.hxx>
 #include <TColStd_SequenceOfHAsciiString.hxx>
 #include <TCollection_HAsciiString.hxx>
-#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
 
 using namespace SMESH;
 using namespace SMESH::Controls;
@@ -72,358 +72,6 @@ namespace SMESH
   }
 }
 
-
-/*
-  Class       : BelongToGeom
-  Description : Predicate for verifying whether entity belongs to
-                specified geometrical support
-*/
-
-Controls::BelongToGeom::BelongToGeom()
-  : myMeshDS(NULL),
-    myType(SMDSAbs_All),
-    myIsSubshape(false),
-    myTolerance(Precision::Confusion())
-{}
-
-void Controls::BelongToGeom::SetMesh( const SMDS_Mesh* theMesh )
-{
-  myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
-  init();
-}
-
-void Controls::BelongToGeom::SetGeom( const TopoDS_Shape& theShape )
-{
-  myShape = theShape;
-  init();
-}
-
-static bool IsSubShape (const TopTools_IndexedMapOfShape& theMap,
-                        const TopoDS_Shape& theShape)
-{
-  if (theMap.Contains(theShape)) return true;
-
-  if (theShape.ShapeType() == TopAbs_COMPOUND ||
-      theShape.ShapeType() == TopAbs_COMPSOLID)
-  {
-    TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
-    for (; anIt.More(); anIt.Next())
-    {
-      if (!IsSubShape(theMap, anIt.Value())) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  return false;
-}
-
-void Controls::BelongToGeom::init()
-{
-  if (!myMeshDS || myShape.IsNull()) return;
-
-  // is sub-shape of main shape?
-  TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh();
-  if (aMainShape.IsNull()) {
-    myIsSubshape = false;
-  }
-  else {
-    TopTools_IndexedMapOfShape aMap;
-    TopExp::MapShapes(aMainShape, aMap);
-    myIsSubshape = IsSubShape(aMap, myShape);
-  }
-
-  if (!myIsSubshape)
-  {
-    myElementsOnShapePtr.reset(new Controls::ElementsOnShape());
-    myElementsOnShapePtr->SetTolerance(myTolerance);
-    myElementsOnShapePtr->SetAllNodes(true); // belong, while false means "lays on"
-    myElementsOnShapePtr->SetMesh(myMeshDS);
-    myElementsOnShapePtr->SetShape(myShape, myType);
-  }
-}
-
-static bool IsContains( const SMESHDS_Mesh*     theMeshDS,
-                        const TopoDS_Shape&     theShape,
-                        const SMDS_MeshElement* theElem,
-                        TopAbs_ShapeEnum        theFindShapeEnum,
-                        TopAbs_ShapeEnum        theAvoidShapeEnum = TopAbs_SHAPE )
-{
-  TopExp_Explorer anExp( theShape,theFindShapeEnum,theAvoidShapeEnum );
-
-  while( anExp.More() )
-  {
-    const TopoDS_Shape& aShape = anExp.Current();
-    if( SMESHDS_SubMesh* aSubMesh = theMeshDS->MeshElements( aShape ) ){
-      if( aSubMesh->Contains( theElem ) )
-        return true;
-    }
-    anExp.Next();
-  }
-  return false;
-}
-
-bool Controls::BelongToGeom::IsSatisfy (long theId)
-{
-  if (myMeshDS == 0 || myShape.IsNull())
-    return false;
-
-  if (!myIsSubshape)
-  {
-    return myElementsOnShapePtr->IsSatisfy(theId);
-  }
-
-  // Case of submesh
-  if (myType == SMDSAbs_Node)
-  {
-    if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
-    {
-      const SMDS_PositionPtr& aPosition = aNode->GetPosition();
-      SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
-      switch( aTypeOfPosition )
-      {
-      case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
-      case SMDS_TOP_EDGE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
-      case SMDS_TOP_FACE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
-      case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
-      }
-    }
-  }
-  else
-  {
-    if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
-    {
-      if( myType == SMDSAbs_All )
-      {
-        return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-               IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
-      }
-      else if( myType == anElem->GetType() )
-      {
-        switch( myType )
-        {
-        case SMDSAbs_Edge  : return IsContains( myMeshDS,myShape,anElem,TopAbs_EDGE );
-        case SMDSAbs_Face  : return IsContains( myMeshDS,myShape,anElem,TopAbs_FACE );
-        case SMDSAbs_Volume: return IsContains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-                                    IsContains( myMeshDS,myShape,anElem,TopAbs_SOLID );
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
-void Controls::BelongToGeom::SetType (SMDSAbs_ElementType theType)
-{
-  myType = theType;
-  init();
-}
-
-SMDSAbs_ElementType Controls::BelongToGeom::GetType() const
-{
-  return myType;
-}
-
-TopoDS_Shape Controls::BelongToGeom::GetShape()
-{
-  return myShape;
-}
-
-const SMESHDS_Mesh* Controls::BelongToGeom::GetMeshDS() const
-{
-  return myMeshDS;
-}
-
-void Controls::BelongToGeom::SetTolerance (double theTolerance)
-{
-  myTolerance = theTolerance;
-  if (!myIsSubshape)
-    init();
-}
-
-double Controls::BelongToGeom::GetTolerance()
-{
-  return myTolerance;
-}
-
-/*
-  Class       : LyingOnGeom
-  Description : Predicate for verifying whether entiy lying or partially lying on
-                specified geometrical support
-*/
-
-Controls::LyingOnGeom::LyingOnGeom()
-  : myMeshDS(NULL),
-    myType(SMDSAbs_All),
-    myIsSubshape(false),
-    myTolerance(Precision::Confusion())
-{}
-
-void Controls::LyingOnGeom::SetMesh( const SMDS_Mesh* theMesh )
-{
-  myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
-  init();
-}
-
-void Controls::LyingOnGeom::SetGeom( const TopoDS_Shape& theShape )
-{
-  myShape = theShape;
-  init();
-}
-
-void Controls::LyingOnGeom::init()
-{
-  if (!myMeshDS || myShape.IsNull()) return;
-
-  // is sub-shape of main shape?
-  TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh();
-  if (aMainShape.IsNull()) {
-    myIsSubshape = false;
-  }
-  else {
-    TopTools_IndexedMapOfShape aMap;
-    TopExp::MapShapes(aMainShape, aMap);
-    myIsSubshape = IsSubShape(aMap, myShape);
-  }
-
-  if (!myIsSubshape)
-  {
-    myElementsOnShapePtr.reset(new Controls::ElementsOnShape());
-    myElementsOnShapePtr->SetTolerance(myTolerance);
-    myElementsOnShapePtr->SetAllNodes(false); // lays on, while true means "belong"
-    myElementsOnShapePtr->SetMesh(myMeshDS);
-    myElementsOnShapePtr->SetShape(myShape, myType);
-  }
-}
-
-bool Controls::LyingOnGeom::IsSatisfy( long theId )
-{
-  if ( myMeshDS == 0 || myShape.IsNull() )
-    return false;
-
-  if (!myIsSubshape)
-  {
-    return myElementsOnShapePtr->IsSatisfy(theId);
-  }
-
-  // Case of submesh
-  if( myType == SMDSAbs_Node )
-  {
-    if( const SMDS_MeshNode* aNode = myMeshDS->FindNode( theId ) )
-    {
-      const SMDS_PositionPtr& aPosition = aNode->GetPosition();
-      SMDS_TypeOfPosition aTypeOfPosition = aPosition->GetTypeOfPosition();
-      switch( aTypeOfPosition )
-      {
-      case SMDS_TOP_VERTEX : return IsContains( myMeshDS,myShape,aNode,TopAbs_VERTEX );
-      case SMDS_TOP_EDGE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_EDGE );
-      case SMDS_TOP_FACE   : return IsContains( myMeshDS,myShape,aNode,TopAbs_FACE );
-      case SMDS_TOP_3DSPACE: return IsContains( myMeshDS,myShape,aNode,TopAbs_SHELL );
-      }
-    }
-  }
-  else
-  {
-    if( const SMDS_MeshElement* anElem = myMeshDS->FindElement( theId ) )
-    {
-      if( myType == SMDSAbs_All )
-      {
-        return Contains( myMeshDS,myShape,anElem,TopAbs_EDGE ) ||
-               Contains( myMeshDS,myShape,anElem,TopAbs_FACE ) ||
-               Contains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-               Contains( myMeshDS,myShape,anElem,TopAbs_SOLID );
-      }
-      else if( myType == anElem->GetType() )
-      {
-        switch( myType )
-        {
-        case SMDSAbs_Edge  : return Contains( myMeshDS,myShape,anElem,TopAbs_EDGE );
-        case SMDSAbs_Face  : return Contains( myMeshDS,myShape,anElem,TopAbs_FACE );
-        case SMDSAbs_Volume: return Contains( myMeshDS,myShape,anElem,TopAbs_SHELL )||
-                                    Contains( myMeshDS,myShape,anElem,TopAbs_SOLID );
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
-void Controls::LyingOnGeom::SetType( SMDSAbs_ElementType theType )
-{
-  myType = theType;
-  init();
-}
-
-SMDSAbs_ElementType Controls::LyingOnGeom::GetType() const
-{
-  return myType;
-}
-
-TopoDS_Shape Controls::LyingOnGeom::GetShape()
-{
-  return myShape;
-}
-
-const SMESHDS_Mesh* Controls::LyingOnGeom::GetMeshDS() const
-{
-  return myMeshDS;
-}
-
-void Controls::LyingOnGeom::SetTolerance (double theTolerance)
-{
-  myTolerance = theTolerance;
-  if (!myIsSubshape)
-    init();
-}
-
-double Controls::LyingOnGeom::GetTolerance()
-{
-  return myTolerance;
-}
-
-bool Controls::LyingOnGeom::Contains( const SMESHDS_Mesh*     theMeshDS,
-                                      const TopoDS_Shape&     theShape,
-                                      const SMDS_MeshElement* theElem,
-                                      TopAbs_ShapeEnum        theFindShapeEnum,
-                                      TopAbs_ShapeEnum        theAvoidShapeEnum )
-{
-  if (IsContains(theMeshDS, theShape, theElem, theFindShapeEnum, theAvoidShapeEnum))
-    return true;
-
-  TopTools_IndexedMapOfShape aSubShapes;
-  TopExp::MapShapes( theShape, aSubShapes );
-
-  for (int i = 1; i <= aSubShapes.Extent(); i++)
-  {
-    const TopoDS_Shape& aShape = aSubShapes.FindKey(i);
-
-    if( SMESHDS_SubMesh* aSubMesh = theMeshDS->MeshElements( aShape ) ){
-      if( aSubMesh->Contains( theElem ) )
-        return true;
-
-      SMDS_NodeIteratorPtr aNodeIt = aSubMesh->GetNodes();
-      while ( aNodeIt->more() )
-      {
-        const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>(aNodeIt->next());
-        SMDS_ElemIteratorPtr anElemIt = aNode->GetInverseElementIterator();
-        while ( anElemIt->more() )
-        {
-          const SMDS_MeshElement* anElement = static_cast<const SMDS_MeshElement*>(anElemIt->next());
-          if (anElement == theElem)
-            return true;
-        }
-      }
-    }
-  }
-  return false;
-}
-
-
 /*
                             AUXILIARY METHODS
 */
@@ -586,12 +234,64 @@ SMESH::Histogram* NumericalFunctor_i::GetHistogram(CORBA::Short nbIntervals, COR
   std::vector<int> elements;
   myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues,elements,0,isLogarithmic);
 
-#ifdef WIN32
-  nbIntervals = CORBA::Short( min( nbEvents.size(), funValues.size() - 1));
-#else
-  nbIntervals = CORBA::Short( std::min( nbEvents.size(), funValues.size() - 1));
-#endif
   SMESH::Histogram_var histogram = new SMESH::Histogram;
+
+  nbIntervals = CORBA::Short( Min( int( nbEvents.size()),
+                                   int( funValues.size() - 1 )));
+  if ( nbIntervals > 0 )
+  {
+    histogram->length( nbIntervals );
+    for ( int i = 0; i < nbIntervals; ++i )
+    {
+      HistogramRectangle& rect = histogram[i];
+      rect.nbEvents = nbEvents[i];
+      rect.min = funValues[i];
+      rect.max = funValues[i+1];
+    }
+  }
+  return histogram._retn();
+}
+
+SMESH::Histogram* NumericalFunctor_i::GetLocalHistogram(CORBA::Short              nbIntervals,
+                                                        CORBA::Boolean            isLogarithmic,
+                                                        SMESH::SMESH_IDSource_ptr object)
+{
+  SMESH::Histogram_var histogram = new SMESH::Histogram;
+
+  std::vector<int>    nbEvents;
+  std::vector<double> funValues;
+  std::vector<int>    elements;
+
+  SMDS_ElemIteratorPtr elemIt;
+  if ( SMESH::DownCast< SMESH_GroupOnFilter_i* >( object ) ||
+       SMESH::DownCast< SMESH::Filter_i* >( object ))
+  {
+    elemIt = SMESH_Mesh_i::GetElements( object, GetElementType() );
+    if ( !elemIt ) return histogram._retn();
+  }
+  else
+  {
+    SMESH::SMESH_Mesh_var        mesh = object->GetMesh();
+    SMESH::long_array_var  objNbElems = object->GetNbElementsByType();
+    SMESH::long_array_var meshNbElems = mesh->  GetNbElementsByType();
+    if ( meshNbElems[ GetElementType() ] !=
+         objNbElems [ GetElementType() ] )
+    {
+      elements.reserve( objNbElems[ GetElementType() ]);
+      elemIt = SMESH_Mesh_i::GetElements( object, GetElementType() );
+    }
+  }
+  if ( elemIt )
+  {
+    while ( elemIt->more() )
+      elements.push_back( elemIt->next()->GetID() );
+    if ( elements.empty() ) return histogram._retn();
+  }
+
+  myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues,elements,0,isLogarithmic);
+
+  nbIntervals = CORBA::Short( Min( int( nbEvents.size()),
+                                   int( funValues.size() - 1 )));
   if ( nbIntervals > 0 )
   {
     histogram->length( nbIntervals );
@@ -918,6 +618,29 @@ CORBA::Boolean Predicate_i::IsSatisfy( CORBA::Long theId )
   return myPredicatePtr->IsSatisfy( theId );
 }
 
+CORBA::Long Predicate_i::NbSatisfying( SMESH::SMESH_IDSource_ptr obj )
+{
+  SMESH::SMESH_Mesh_var meshVar = obj->GetMesh();
+  const SMDS_Mesh*       meshDS = MeshPtr2SMDSMesh( meshVar );
+  if ( !meshDS )
+    return 0;
+  myPredicatePtr->SetMesh( meshDS );
+
+  SMDSAbs_ElementType elemType = SMDSAbs_ElementType( GetElementType() );
+
+  int nb = 0;
+  SMDS_ElemIteratorPtr elemIt =
+    SMESH::DownCast<SMESH_Mesh_i*>( meshVar )->GetElements( obj, GetElementType() );
+  if ( elemIt )
+    while ( elemIt->more() )
+    {
+      const SMDS_MeshElement* e = elemIt->next();
+      if ( e && e->GetType() == elemType )
+        nb += myPredicatePtr->IsSatisfy( e->GetID() );
+    }
+  return nb;
+}
+
 Controls::PredicatePtr Predicate_i::GetPredicate()
 {
   return myPredicatePtr;
@@ -1710,6 +1433,172 @@ FunctorType CoplanarFaces_i::GetFunctorType()
   return SMESH::FT_CoplanarFaces;
 }
 
+/*
+ * Class       : ConnectedElements_i
+ * Description : Returns true if an element is connected via other elements to the element
+ *               located at a given point.
+ */
+ConnectedElements_i::ConnectedElements_i()
+{
+  myConnectedElementsPtr.reset(new Controls::ConnectedElements());
+  myFunctorPtr = myPredicatePtr = myConnectedElementsPtr;
+}
+
+FunctorType ConnectedElements_i::GetFunctorType()
+{
+  return FT_ConnectedElements;
+}
+
+void ConnectedElements_i::SetElementType( ElementType theType )
+{
+  myConnectedElementsPtr->SetType( SMDSAbs_ElementType( theType ));
+  TPythonDump() << this << ".SetElementType( " << theType << " )";
+}
+
+void ConnectedElements_i::SetPoint( CORBA::Double x, CORBA::Double y, CORBA::Double z )
+{
+  myConnectedElementsPtr->SetPoint( x,y,z );
+  myVertexID.clear();
+  TPythonDump() << this << ".SetPoint( " << x << ", " << y << ", " << z << " )";
+}
+
+void ConnectedElements_i::SetVertex( GEOM::GEOM_Object_ptr vertex )
+  throw (SALOME::SALOME_Exception)
+{
+  TopoDS_Shape shape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( vertex );
+  if ( shape.IsNull() )
+    THROW_SALOME_CORBA_EXCEPTION( "ConnectedElements_i::SetVertex(): NULL Vertex",
+                                  SALOME::BAD_PARAM );
+
+  TopExp_Explorer v( shape, TopAbs_VERTEX );
+  if ( !v.More() )
+    THROW_SALOME_CORBA_EXCEPTION( "ConnectedElements_i::SetVertex(): empty vertex",
+                                  SALOME::BAD_PARAM );
+
+  gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( v.Current() ));
+  myConnectedElementsPtr->SetPoint( p.X(), p.Y(), p.Z() );
+  //
+  CORBA::String_var id = vertex->GetStudyEntry();
+  myVertexID = id.in();
+
+  TPythonDump() << this << ".SetVertex( " << vertex << " )";
+}
+
+void ConnectedElements_i::SetNode ( CORBA::Long nodeID )
+  throw (SALOME::SALOME_Exception)
+{
+  if ( nodeID < 1 )
+    THROW_SALOME_CORBA_EXCEPTION( "ConnectedElements_i::SetNode(): nodeID must be > 0",
+                                  SALOME::BAD_PARAM );
+
+  myConnectedElementsPtr->SetNode( nodeID );
+  myVertexID.clear();
+  TPythonDump() << this << ".SetNode( " << nodeID << " )";
+}
+
+/*!
+ * \brief This is a comfort method for Filter dialog
+ */
+void ConnectedElements_i::SetThreshold ( const char*                             threshold,
+                                         SMESH::ConnectedElements::ThresholdType type )
+  throw (SALOME::SALOME_Exception)
+{
+  if ( !threshold )
+    THROW_SALOME_CORBA_EXCEPTION( "ConnectedElements_i::SetThreshold(): NULL threshold",
+                                  SALOME::BAD_PARAM );
+  switch ( type )
+  {
+  case SMESH::ConnectedElements::POINT: // read 3 node coordinates ///////////////////
+    {
+      vector< double > xyz;
+      char* endptr;
+      do
+      {
+        // skip a separator
+        while ( *threshold &&
+                *threshold != '+' &&
+                *threshold != '-' &&
+                !isdigit( *threshold ))
+          ++threshold;
+        if ( !*threshold )
+          break;
+        // read a coordinate
+        xyz.push_back( strtod( threshold, &endptr ));
+        if ( threshold == endptr )
+        {
+          xyz.resize( xyz.size() - 1 );
+          break;
+        }
+        threshold = endptr;
+      }
+      while ( xyz.size() < 3 );
+
+      if ( xyz.size() < 3 )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "ConnectedElements_i::SetThreshold(): invalid point coordinates", SALOME::BAD_PARAM );
+
+      SetPoint( xyz[0], xyz[1], xyz[2] );
+      break;
+    }
+  case SMESH::ConnectedElements::VERTEX: // get a VERTEX by its entry /////////////////
+    {
+      SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
+      if ( study->_is_nil() )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "ConnectedElements_i::SetThreshold(): NULL current study", SALOME::BAD_PARAM );
+      SALOMEDS::SObject_wrap sobj = study->FindObjectID( threshold );
+      if ( sobj->_is_nil() )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "ConnectedElements_i::SetThreshold(): invalid vertex study entry", SALOME::BAD_PARAM );
+      CORBA::Object_var         obj = sobj->GetObject();
+      GEOM::GEOM_Object_wrap vertex = GEOM::GEOM_Object::_narrow( obj );
+      if ( vertex->_is_nil() )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "ConnectedElements_i::SetThreshold(): no GEOM_Object in SObject", SALOME::BAD_PARAM );
+      SetVertex( vertex );
+      break;
+    }
+  case SMESH::ConnectedElements::NODE: // read a node ID ////////////////////////////
+    {
+      char* endptr;
+      int id = strtol( threshold, &endptr, 10 );
+      if ( threshold == endptr )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "ConnectedElements_i::SetThreshold(): invalid node ID", SALOME::BAD_PARAM );
+      SetNode( id );
+      break;
+    }
+  default:
+    THROW_SALOME_CORBA_EXCEPTION
+      ( "ConnectedElements_i::SetThreshold(): invalid ThresholdType", SALOME::BAD_PARAM );
+  }
+}
+
+char* ConnectedElements_i::GetThreshold ( SMESH::ConnectedElements::ThresholdType& type )
+{
+  std::string threshold;
+  if ( !myVertexID.empty() )
+  {
+    threshold = myVertexID;
+    type      = SMESH::ConnectedElements::VERTEX;
+  }
+  else
+  {
+    std::vector<double> xyz = myConnectedElementsPtr->GetPoint();
+    if ( xyz.size() == 3 )
+    {
+      threshold = SMESH_Comment( xyz[0] ) << "; " << xyz[1] << "; " << xyz[2];
+      type      = SMESH::ConnectedElements::POINT;
+    }
+    else
+    {
+      threshold = SMESH_Comment( myConnectedElementsPtr->GetNode() );
+      type      = SMESH::ConnectedElements::NODE;
+    }
+  }
+  return CORBA::string_dup( threshold.c_str() );
+}
+
 /*
   Class       : Comparator_i
   Description : Base class for comparators
@@ -2160,6 +2049,14 @@ CoplanarFaces_ptr FilterManager_i::CreateCoplanarFaces()
   return anObj._retn();
 }
 
+ConnectedElements_ptr FilterManager_i::CreateConnectedElements()
+{
+  SMESH::ConnectedElements_i* aServant = new SMESH::ConnectedElements_i();
+  SMESH::ConnectedElements_var anObj = aServant->_this();
+  TPythonDump()<<aServant<<" = "<<this<<".CreateConnectedElements()";
+  return anObj._retn();
+}
+
 FreeBorders_ptr FilterManager_i::CreateFreeBorders()
 {
   SMESH::FreeBorders_i* aServant = new SMESH::FreeBorders_i();
@@ -2526,59 +2423,63 @@ GetElementsId( SMESH_Mesh_ptr theMesh )
   return anArray._retn();
 }
 
-template<class TElement, class TIterator, class TPredicate>
-static void collectMeshInfo(const TIterator& theItr,
-                            TPredicate& thePred,
-                            SMESH::long_array& theRes)
-{         
-  if (!theItr)
-    return;
-  while (theItr->more()) {
-    const SMDS_MeshElement* anElem = theItr->next();
-    if ( thePred->IsSatisfy( anElem->GetID() ) )
-      theRes[ anElem->GetEntityType() ]++;
+//=============================================================================
+/*!
+ * \brief Returns number of mesh elements per each \a EntityType
+ */
+//=============================================================================
+
+SMESH::long_array* ::Filter_i::GetMeshInfo()
+{
+  SMESH::long_array_var aRes = new SMESH::long_array();
+  aRes->length(SMESH::Entity_Last);
+  for (int i = 0; i < SMESH::Entity_Last; i++)
+    aRes[i] = 0;
+
+  if ( !CORBA::is_nil(myMesh) && myPredicate )
+  {
+    const SMDS_Mesh*  aMesh = MeshPtr2SMDSMesh(myMesh);
+    SMDS_ElemIteratorPtr it = aMesh->elementsIterator( SMDSAbs_ElementType( GetElementType() ));
+    while ( it->more() )
+    {
+      const SMDS_MeshElement* anElem = it->next();
+      if ( myPredicate->IsSatisfy( anElem->GetID() ) )
+        aRes[ anElem->GetEntityType() ]++;
+    }
   }
+
+  return aRes._retn();  
 }
 
 //=============================================================================
 /*!
- * \brief Returns statistic of mesh elements
+ * \brief Returns number of mesh elements of each \a ElementType
  */
 //=============================================================================
-SMESH::long_array* ::Filter_i::GetMeshInfo()
+
+SMESH::long_array* ::Filter_i::GetNbElementsByType()
 {
   SMESH::long_array_var aRes = new SMESH::long_array();
-  aRes->length(SMESH::Entity_Last);
-  for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
+  aRes->length(SMESH::NB_ELEMENT_TYPES);
+  for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
     aRes[i] = 0;
 
-  if(!CORBA::is_nil(myMesh) && myPredicate) {
-    const SMDS_Mesh* aMesh = MeshPtr2SMDSMesh(myMesh);
-    SMDS_ElemIteratorPtr it;
-    switch( GetElementType() )
+  if ( !CORBA::is_nil(myMesh) && myPredicate ) {
+    const SMDS_Mesh*  aMesh = MeshPtr2SMDSMesh(myMesh);
+    SMDS_ElemIteratorPtr it = aMesh->elementsIterator( SMDSAbs_ElementType( GetElementType() ));
+    CORBA::Long& nbElems = aRes[ GetElementType() ];
+    while ( it->more() )
     {
-    case SMDSAbs_Node:
-      collectMeshInfo<const SMDS_MeshNode*>(aMesh->nodesIterator(),myPredicate,aRes);
-      break;
-    case SMDSAbs_Edge:
-      collectMeshInfo<const SMDS_MeshElement*>(aMesh->edgesIterator(),myPredicate,aRes);
-      break;
-    case SMDSAbs_Face:
-      collectMeshInfo<const SMDS_MeshElement*>(aMesh->facesIterator(),myPredicate,aRes);
-      break;
-    case SMDSAbs_Volume:
-      collectMeshInfo<const SMDS_MeshElement*>(aMesh->volumesIterator(),myPredicate,aRes);
-      break;
-    case SMDSAbs_All:
-    default:
-      collectMeshInfo<const SMDS_MeshElement*>(aMesh->elementsIterator(),myPredicate,aRes);
-      break;
+      const SMDS_MeshElement* anElem = it->next();
+      if ( myPredicate->IsSatisfy( anElem->GetID() ) )
+        nbElems++;
     }
   }
 
   return aRes._retn();  
 }
 
+
 //================================================================================
 /*!
  * \brief Return GetElementType() within an array
@@ -2648,6 +2549,40 @@ static inline bool getCriteria( Predicate_i*                thePred,
 {
   int aFType = thePred->GetFunctorType();
 
+  switch ( aFType )
+  {
+  case FT_LogicalNOT:
+    {
+      Predicate_i* aPred = ( dynamic_cast<LogicalNOT_i*>( thePred ) )->GetPredicate_i();
+      getCriteria( aPred, theCriteria );
+      theCriteria[ theCriteria->length() - 1 ].UnaryOp = FT_LogicalNOT;
+    }
+    return true;
+
+  case FT_LogicalAND:
+  case FT_LogicalOR:
+    {
+      Predicate_i* aPred1 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate1_i();
+      Predicate_i* aPred2 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate2_i();
+      if ( !getCriteria( aPred1, theCriteria ) )
+        return false;
+      theCriteria[ theCriteria->length() - 1 ].BinaryOp = aFType;
+      return getCriteria( aPred2, theCriteria );
+    }
+  case FT_Undefined:
+    return false;
+  }
+
+  // resize theCriteria
+  CORBA::ULong i = theCriteria->length();
+  theCriteria->length( i + 1 );
+  theCriteria[ i ] = createCriterion();
+
+  // set members of the added Criterion
+
+  theCriteria[ i ].Type = aFType;
+  theCriteria[ i ].TypeOfElement = thePred->GetElementType();
+
   switch ( aFType )
   {
   case FT_FreeBorders:
@@ -2664,30 +2599,14 @@ static inline bool getCriteria( Predicate_i*                thePred,
   case FT_OverConstrainedVolume:
   case FT_OverConstrainedFace:
     {
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type = aFType;
-      theCriteria[ i ].TypeOfElement = thePred->GetElementType();
       return true;
     }
   case FT_BelongToGeom:
     {
       BelongToGeom_i* aPred = dynamic_cast<BelongToGeom_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type          = FT_BelongToGeom;
       theCriteria[ i ].ThresholdStr  = aPred->GetShapeName();
       theCriteria[ i ].ThresholdID   = aPred->GetShapeID();
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
       theCriteria[ i ].Tolerance     = aPred->GetTolerance();
-
       return true;
     }
   case FT_BelongToPlane:
@@ -2695,80 +2614,52 @@ static inline bool getCriteria( Predicate_i*                thePred,
   case FT_BelongToGenSurface:
     {
       BelongToSurface_i* aPred = dynamic_cast<BelongToSurface_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type          = aFType;
       theCriteria[ i ].ThresholdStr  = aPred->GetShapeName();
       theCriteria[ i ].ThresholdID   = aPred->GetShapeID();
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
       theCriteria[ i ].Tolerance     = aPred->GetTolerance();
-
       return true;
     }
-   case FT_LyingOnGeom:
+  case FT_LyingOnGeom:
     {
       LyingOnGeom_i* aPred = dynamic_cast<LyingOnGeom_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type          = FT_LyingOnGeom;
       theCriteria[ i ].ThresholdStr  = aPred->GetShapeName();
       theCriteria[ i ].ThresholdID   = aPred->GetShapeID();
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
       theCriteria[ i ].Tolerance     = aPred->GetTolerance();
-
       return true;
     }
-   case FT_CoplanarFaces:
+  case FT_CoplanarFaces:
     {
       CoplanarFaces_i* aPred = dynamic_cast<CoplanarFaces_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-      CORBA::String_var faceId = aPred->GetFaceAsString();
-
-      theCriteria[ i ].Type          = FT_CoplanarFaces;
-      theCriteria[ i ].ThresholdID   = faceId;
+      theCriteria[ i ].ThresholdID   = aPred->GetFaceAsString();
       theCriteria[ i ].Tolerance     = aPred->GetTolerance();
-
+      return true;
+    }
+  case FT_ConnectedElements:
+    {
+      ConnectedElements_i* aPred = dynamic_cast<ConnectedElements_i*>( thePred );
+      SMESH::ConnectedElements::ThresholdType type;
+      CORBA::String_var threshold = aPred->GetThreshold( type );
+      switch ( type ) {
+      case SMESH::ConnectedElements::POINT:
+        theCriteria[ i ].ThresholdStr = threshold; break;
+      case SMESH::ConnectedElements::VERTEX:
+        theCriteria[ i ].ThresholdID = threshold; break;
+      case SMESH::ConnectedElements::NODE:
+        theCriteria[ i ].Threshold = atof( threshold.in() ); break;
+      default:;
+      }
       return true;
     }
   case FT_EqualNodes:
     {
       EqualNodes_i* aPred = dynamic_cast<EqualNodes_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type          = FT_EqualNodes;
-      theCriteria[ i ].Tolerance     = aPred->GetTolerance();
-
+      theCriteria[ i ].Tolerance  = aPred->GetTolerance();
       return true;
     }
   case FT_RangeOfIds:
     {
       RangeOfIds_i* aPred = dynamic_cast<RangeOfIds_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
-      theCriteria[ i ].Type          = FT_RangeOfIds;
       theCriteria[ i ].ThresholdStr  = aPred->GetRangeStr();
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
-
       return true;
     }
   case FT_LessThan:
@@ -2776,85 +2667,34 @@ static inline bool getCriteria( Predicate_i*                thePred,
   case FT_EqualTo:
     {
       Comparator_i* aCompar = dynamic_cast<Comparator_i*>( thePred );
-
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
       theCriteria[ i ].Type      = aCompar->GetNumFunctor_i()->GetFunctorType();
       theCriteria[ i ].Compare   = aFType;
       theCriteria[ i ].Threshold = aCompar->GetMargin();
-      theCriteria[ i ].TypeOfElement = aCompar->GetElementType();
-
       if ( aFType == FT_EqualTo )
       {
         EqualTo_i* aCompar = dynamic_cast<EqualTo_i*>( thePred );
         theCriteria[ i ].Tolerance = aCompar->GetTolerance();
       }
-    }
-    return true;
-
-  case FT_LogicalNOT:
-    {
-      Predicate_i* aPred = ( dynamic_cast<LogicalNOT_i*>( thePred ) )->GetPredicate_i();
-      getCriteria( aPred, theCriteria );
-      theCriteria[ theCriteria->length() - 1 ].UnaryOp = FT_LogicalNOT;
-    }
-    return true;
-
-  case FT_LogicalAND:
-  case FT_LogicalOR:
-    {
-      Predicate_i* aPred1 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate1_i();
-      Predicate_i* aPred2 = ( dynamic_cast<LogicalBinary_i*>( thePred ) )->GetPredicate2_i();
-      if ( !getCriteria( aPred1, theCriteria ) )
-        return false;
-      theCriteria[ theCriteria->length() - 1 ].BinaryOp = aFType;
-      return getCriteria( aPred2, theCriteria );
+      return true;
     }
   case FT_GroupColor:
     {
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
       GroupColor_i* aPred = dynamic_cast<GroupColor_i*>( thePred );
-      theCriteria[ i ].Type          = aFType;
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
-      theCriteria[ i ].ThresholdStr  = aPred->GetColorStr();
-
+      theCriteria[ i ].ThresholdStr = aPred->GetColorStr();
       return true;
     }
   case FT_ElemGeomType:
     {
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
       ElemGeomType_i* aPred = dynamic_cast<ElemGeomType_i*>( thePred );
-      theCriteria[ i ].Type          = aFType;
-      theCriteria[ i ].TypeOfElement = aPred->GetElementType();
-      theCriteria[ i ].Threshold     = (double)aPred->GetGeometryType();
+      theCriteria[ i ].Threshold = (double)aPred->GetGeometryType();
       return true;
     }
   case FT_EntityType:
     {
-      CORBA::ULong i = theCriteria->length();
-      theCriteria->length( i + 1 );
-
-      theCriteria[ i ] = createCriterion();
-
       ElemEntityType_i* aPred = dynamic_cast<ElemEntityType_i*>( thePred );
-      theCriteria[ i ].Type          = aFType;
-      theCriteria[ i ].Threshold     = (double)aPred->GetEntityType();
+      theCriteria[ i ].Threshold = (double)aPred->GetEntityType();
       return true;
     }
-
-  case FT_Undefined:
-    return false;
   default:
     return false;
   }
@@ -2876,8 +2716,7 @@ CORBA::Boolean Filter_i::GetCriteria( SMESH::Filter::Criteria_out theCriteria )
 //=======================================================================
 CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria )
 {
-  if ( myPredicate != 0 )
-    myPredicate->UnRegister();
+  SetPredicate( SMESH::Predicate::_nil() );
 
   SMESH::FilterManager_i* aFilter = new SMESH::FilterManager_i();
   FilterManager_ptr aFilterMgr = aFilter->_this();
@@ -2907,9 +2746,8 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
          << aCriterion    << ", "
          << aCompare      << ", "
          << aThreshold    << ", '"
-         << aThresholdStr << "', '";
-      if (aThresholdID) pd << aThresholdID;
-      pd                  << "', "
+         << aThresholdStr << "', '"
+         << aThresholdID  << "', "
          << aUnary        << ", "
          << aBinary       << ", "
          << aTolerance    << ", "
@@ -3109,6 +2947,19 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
           aPredicate = tmpPred;
           break;
         }
+      case SMESH::FT_ConnectedElements:
+        {
+          SMESH::ConnectedElements_ptr tmpPred = aFilterMgr->CreateConnectedElements();
+          if ( strlen( aThresholdID ) > 0 ) // shape ID
+            tmpPred->SetThreshold( aThresholdID, SMESH::ConnectedElements::VERTEX );
+          else if ( strlen( aThresholdStr ) > 0 ) // point coords
+            tmpPred->SetThreshold( aThresholdStr, SMESH::ConnectedElements::POINT );
+          else if ( aThreshold >= 1 )
+            tmpPred->SetNode( (CORBA::Long) aThreshold ); // node ID
+          tmpPred->SetElementType( aTypeOfElem );
+          aPredicate = tmpPred;
+          break;
+        }
 
       default:
         continue;
@@ -3217,6 +3068,8 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
   }
 
   SetPredicate( aResPredicate );
+  if ( !aResPredicate->_is_nil() )
+    aResPredicate->UnRegister();
 
   return !aResPredicate->_is_nil();
 }
@@ -3966,6 +3819,7 @@ static const char** getFunctNames()
     "FT_EntityType", 
     "FT_CoplanarFaces",
     "FT_BallDiameter",
+    "FT_ConnectedElements",
     "FT_LessThan",
     "FT_MoreThan",
     "FT_EqualTo",