Salome HOME
22877: EDF 10054 SMESH: Add a new filter "BelongToSmeshGroup" for Create Group
authoreap <eap@opencascade.com>
Tue, 14 Apr 2015 12:39:28 +0000 (15:39 +0300)
committereap <eap@opencascade.com>
Tue, 14 Apr 2015 12:39:28 +0000 (15:39 +0300)
24 files changed:
doc/salome/examples/CMakeLists.txt
doc/salome/examples/filters_belong2group.py [new file with mode: 0644]
doc/salome/gui/SMESH/input/about_filters.doc
doc/salome/gui/SMESH/input/selection_filter_library.doc
doc/salome/gui/SMESH/input/tui_filters.doc
idl/SMESH_Filter.idl
idl/SMESH_Group.idl
src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx
src/SMESHDS/SMESH_Controls.hxx
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_FilterDlg.h
src/SMESHGUI/SMESHGUI_FilterLibraryDlg.cxx
src/SMESHGUI/SMESHGUI_GroupDlg.cxx
src/SMESHGUI/SMESHGUI_VTKUtils.cxx
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_DumpPython.cxx
src/SMESH_I/SMESH_Filter_i.cxx
src/SMESH_I/SMESH_Filter_i.hxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Group_i.cxx
src/SMESH_I/SMESH_Group_i.hxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_SWIG/smeshBuilder.py

index 8780e9389191cbe030b40039db37fef0685af2ba..7ee8ff5fda3ebf1c2602f6548392862606fdc6ee 100644 (file)
@@ -95,6 +95,7 @@ SET(GOOD_TESTS
   filters_ex33.py
   filters_ex34.py
   filters_ex36.py
+  filters_belong2group.py
   grouping_elements_ex01.py
   grouping_elements_ex02.py
   grouping_elements_ex03.py
diff --git a/doc/salome/examples/filters_belong2group.py b/doc/salome/examples/filters_belong2group.py
new file mode 100644 (file)
index 0000000..889c0ae
--- /dev/null
@@ -0,0 +1,18 @@
+# Belong to Mesh Group criterion
+
+# create mesh
+from SMESH_mechanic import *
+
+# create a group of all faces (quadrangles) generated on sub_face3
+faces_on_face3 = mesh.MakeGroup("faces_on_face3", SMESH.FACE, SMESH.FT_BelongToGeom,'=',sub_face3)
+print "There are %s quadrangles generated on '%s' and included in the group '%s'" % ( faces_on_face3.Size(), sub_face3.GetName(), faces_on_face3.GetName() )
+
+# create a group of all the rest quadrangles, generated on other faces by combining 2 criteria:
+# - negated FT_BelongToMeshGroup to select elements not included in faces_on_face3
+# - FT_ElemGeomType to select quadrangles
+not_on_face3 = smesh.GetCriterion( SMESH.FACE, SMESH.FT_BelongToMeshGroup,'=',faces_on_face3, SMESH.FT_LogicalNOT )
+quadrangles  = smesh.GetCriterion( SMESH.FACE, SMESH.FT_ElemGeomType,'=',SMESH.Geom_QUADRANGLE )
+
+rest_quads = mesh.MakeGroupByCriteria("rest_quads", [ not_on_face3, quadrangles ])
+print "'%s' group includes all the rest %s quadrangles" % ( rest_quads.GetName(), rest_quads.Size() )
+
index d05b8f09a6f701863fb334c2e72eb6e9d56d16f8..bbd5960235c607d75f20042b18b3542644d63b14 100644 (file)
@@ -11,7 +11,7 @@ Several criteria can be combined together by using logical operators \a
 AND and \a OR. In addition, applied filter criterion can be reverted
 using logical operator \a NOT.
 
-Mesh filters use the functionality of \ref quality_page "mesh quality controls"
+Some filtering criteria use the functionality of \ref quality_page "mesh quality controls"
 to filter mesh nodes / elements by specific characteristic (Area, Length, etc).
 
 The functinality of mesh filters is available in both GUI and TUI
index a0e85ab81bbf06265b9cac5991ed7976836421ed..6ab408ee1491517995408b73551de4308fe503f4 100644 (file)
@@ -24,8 +24,8 @@ menu for setting filters looks a bit differently (see the image below).
 
 Each filter can be applicable to \b Nodes, \b Edges, \b Faces or \b
 Volumes. You can combine many criteria in one filter, but they all
-must be of the same <b>Entity type</b>.
-\n The \b Add button creates a new criterion at the end of the list of
+must be of the same <b>Entity type</b>. <br>
+The \b Add button creates a new criterion at the end of the list of
 criteria. The \b Insert button creates a new criterion before the
 selected criterion. The \b Remove button deletes the selected
 criterion. The \b Clear button deletes all criteria.
@@ -43,11 +43,11 @@ selection of elements in the Viewer to the current filter.
 <br>
 In the \b Source field you choose if the filter will be applied to
 the whole \b Mesh, the <b>Initial Selection</b> or the <b>Current
-Group</b>. If \b Mesh is chosen, the elements satisfying the filter
+Dialog</b>. If \b Mesh is chosen, the elements satisfying the filter
 will be selected in the 3D Viewer. If <b> Initial Selection</b> is
 chosen, the filter will be applied to the selected elements and the
 elements rejected by the filter will be deselected. If <b>Current
-Group</b> is chosen, the filter will be applied to the list of
+Dialog</b> is chosen, the filter will be applied to the list of
 elements in the current dialog and the elements rejected
 by the filter will be removed from the list.
 <br>
@@ -76,6 +76,9 @@ If the threshold shape is a sub-shape of the main shape of the mesh the
 algorithm works faster, if this is any other
 shape, the algorithm works slower.
 </li><li>
+<b>Belong to Mesh Group</b> selects entities included into a mesh group
+defined by <b>Threshold Value</b>.
+</li><li>
 <b>Range of IDs</b> allows selection of entities with the specified
 IDs. 
 <b>Threshold Value</b> can be, for example: "1,2,3,50-60,63,67,70-78"
index 856c7fe9b139b26324be915a903b60e922587738..bf3a1f72e23a4180e163ca9407571d6cd1dfaede 100755 (executable)
@@ -2,14 +2,16 @@
 
 \page tui_filters_page Filters usage
 
+\tableofcontents
+
 Filters allow picking only the mesh elements satisfying to a
 specific condition or a set of conditions. Filters can be used to create
 or edit mesh groups, remove elements from the mesh object, control
 mesh quality by different parameters, etc.
 
-Several filters can be combined together by using logical operators \a
-AND and \a OR. In addition, applied filter criterion can be reverted
-using logical operator \a NOT.
+Several filtering criteria can be combined together by using logical
+operators \a AND and \a OR. In addition, applied filter criterion can
+be reverted using logical operator \a NOT.
 
 Mesh filters use the functionality of mesh quality controls to filter
 mesh nodes / elements by a specific characteristic (Area, Length, etc).
@@ -300,6 +302,16 @@ Filter over-constrained volumes:
 
 \sa \ref tui_over_constrained_faces
 
+\section filter_belong_to_group Belong to Mesh Group
+
+Filter mesh entities (nodes or elements) included in a mesh group
+defined by threshold value:
+- element type can be any entity type, from \a  SMESH.NODE to \a SMESH.VOLUME
+- functor type should be \a SMESH.FT_BelongToMeshGroup
+- threshold is mesh group object
+
+\tui_script{filters_belong2group.py}
+
 \section filter_belong_to_geom Belong to Geom
 
 Filter mesh entities (nodes or elements) which all nodes lie on the
index 42147a21f4c260dfdd9c7857614fc7181de5ced4..738aa325e45af6bed4ba03ffcad84441d737a2e2 100644 (file)
@@ -61,6 +61,7 @@ module SMESH
     FT_MultiConnection2D,
     FT_Length,
     FT_Length2D,
+    FT_BelongToMeshGroup,
     FT_BelongToGeom,
     FT_BelongToPlane,
     FT_BelongToCylinder,
@@ -228,6 +229,17 @@ module SMESH
    */
   interface EqualVolumes: Predicate {};
 
+  /*!
+  * Logical functor (predicate) "Belong To Mesh Group".
+  * Verify whether a mesh element is included into a mesh group
+  */
+  interface BelongToMeshGroup: Predicate
+  {
+    void SetGroup( in SMESH::SMESH_GroupBase theGroup );
+    void SetGroupID( in string theID ); // IOR or StoreName
+    SMESH::SMESH_GroupBase GetGroup();
+  };
+
   /*!
    * Logical functor (predicate) "Belong To Geometry".
    * Verify whether mesh element or node belong to pointed Geom Object
@@ -559,59 +571,60 @@ module SMESH
     /*!
     *  Create numerical functors
     */
-    MinimumAngle      CreateMinimumAngle();
-    AspectRatio       CreateAspectRatio();
-    AspectRatio3D     CreateAspectRatio3D();
-    Warping           CreateWarping();
-    Taper             CreateTaper();
-    Skew              CreateSkew();
-    Area              CreateArea();
-    Volume3D          CreateVolume3D();
+    MinimumAngle       CreateMinimumAngle();
+    AspectRatio        CreateAspectRatio();
+    AspectRatio3D      CreateAspectRatio3D();
+    Warping            CreateWarping();
+    Taper              CreateTaper();
+    Skew               CreateSkew();
+    Area               CreateArea();
+    Volume3D           CreateVolume3D();
     MaxElementLength2D CreateMaxElementLength2D();
     MaxElementLength3D CreateMaxElementLength3D();
-    Length            CreateLength();
-    Length2D          CreateLength2D();
-    MultiConnection   CreateMultiConnection();
-    MultiConnection2D CreateMultiConnection2D();
-    BallDiameter      CreateBallDiameter();
+    Length             CreateLength();
+    Length2D           CreateLength2D();
+    MultiConnection    CreateMultiConnection();
+    MultiConnection2D  CreateMultiConnection2D();
+    BallDiameter       CreateBallDiameter();
     /*!
-    *  Create logical functors ( predicates )
-    */
-    BelongToGeom      CreateBelongToGeom();
-    BelongToPlane     CreateBelongToPlane();
-    BelongToCylinder  CreateBelongToCylinder();
+     *  Create logical functors ( predicates )
+     */
+    BelongToMeshGroup  CreateBelongToMeshGroup();
+    BelongToGeom       CreateBelongToGeom();
+    BelongToPlane      CreateBelongToPlane();
+    BelongToCylinder   CreateBelongToCylinder();
     BelongToGenSurface CreateBelongToGenSurface();
 
-    LyingOnGeom       CreateLyingOnGeom();
+    LyingOnGeom        CreateLyingOnGeom();
 
-    FreeBorders       CreateFreeBorders();
-    FreeEdges         CreateFreeEdges();
-    FreeNodes         CreateFreeNodes();
-    FreeFaces         CreateFreeFaces();
+    FreeBorders        CreateFreeBorders();
+    FreeEdges          CreateFreeEdges();
+    FreeNodes          CreateFreeNodes();
+    FreeFaces          CreateFreeFaces();
 
-    EqualNodes        CreateEqualNodes();
-    EqualEdges        CreateEqualEdges();
-    EqualFaces        CreateEqualFaces();
-    EqualVolumes      CreateEqualVolumes();
+    EqualNodes         CreateEqualNodes();
+    EqualEdges         CreateEqualEdges();
+    EqualFaces         CreateEqualFaces();
+    EqualVolumes       CreateEqualVolumes();
 
-    RangeOfIds        CreateRangeOfIds();
+    RangeOfIds         CreateRangeOfIds();
 
-    BadOrientedVolume CreateBadOrientedVolume();
-    BareBorderVolume  CreateBareBorderVolume();
-    BareBorderFace    CreateBareBorderFace();
+    BadOrientedVolume  CreateBadOrientedVolume();
+    BareBorderVolume   CreateBareBorderVolume();
+    BareBorderFace     CreateBareBorderFace();
     OverConstrainedVolume CreateOverConstrainedVolume();
     OverConstrainedFace   CreateOverConstrainedFace();
-    LinearOrQuadratic CreateLinearOrQuadratic();
+    LinearOrQuadratic  CreateLinearOrQuadratic();
 
-    GroupColor        CreateGroupColor();
-    ElemGeomType      CreateElemGeomType();
-    ElemEntityType    CreateElemEntityType();
-    CoplanarFaces     CreateCoplanarFaces();
-    ConnectedElements CreateConnectedElements();
+    GroupColor         CreateGroupColor();
+    ElemGeomType       CreateElemGeomType();
+    ElemEntityType     CreateElemEntityType();
+    CoplanarFaces      CreateCoplanarFaces();
+    ConnectedElements  CreateConnectedElements();
 
     /*!
-    *  Create comparators ( predicates )
-    */
+     *  Create comparators ( predicates )
+     */
     LessThan          CreateLessThan();
     MoreThan          CreateMoreThan();
     EqualTo           CreateEqualTo();
index db6a0f331f6e8b121ade81bb0416101e3571d258..4941f14df5c8ec12a8c87d6fc708b27437313c0c 100644 (file)
@@ -121,7 +121,13 @@ module SMESH
      * (corresponds to the "hue" parameter of the color - must be in range [0, 360])
      */
     long GetColorNumber();
-  }; 
+
+    /*!
+     * Returns \c true if \c this group depends on the \a other via
+     * FT_BelongToMeshGroup predicate or vice versa
+     */
+    boolean IsInDependency( in SMESH_GroupBase other );
+  };
 
   /*!
    * SMESH_Group: interface of a standalone group object
@@ -170,7 +176,7 @@ module SMESH
    */
   interface SMESH_GroupOnFilter : SMESH_GroupBase
   {
-    void   SetFilter( in Filter theFilter); 
+    void   SetFilter( in Filter theFilter) raises (SALOME::SALOME_Exception)
     Filter GetFilter();
   };
 
index 48c4d878d668a2212f3bc50a36095a64f46f5ed8..a5739224fca1a76d999ccc320c30c66522741f09 100644 (file)
@@ -3820,9 +3820,55 @@ void ManifoldPart::getFacesByLink( const ManifoldPart::Link& theLink,
   }
 }
 
+/*
+  Class       : BelongToMeshGroup
+  Description : Verify whether a mesh element is included into a mesh group
+*/
+BelongToMeshGroup::BelongToMeshGroup(): myGroup( 0 )
+{
+}
+
+void BelongToMeshGroup::SetGroup( SMESHDS_GroupBase* g )
+{
+  myGroup = g;
+}
+
+void BelongToMeshGroup::SetStoreName( const std::string& sn )
+{
+  myStoreName = sn;
+}
+
+void BelongToMeshGroup::SetMesh( const SMDS_Mesh* theMesh )
+{
+  if ( myGroup && myGroup->GetMesh() != theMesh )
+  {
+    myGroup = 0;
+  }
+  if ( !myGroup && !myStoreName.empty() )
+  {
+    if ( const SMESHDS_Mesh* aMesh = dynamic_cast<const SMESHDS_Mesh*>(theMesh))
+    {
+      const std::set<SMESHDS_GroupBase*>& grps = aMesh->GetGroups();
+      std::set<SMESHDS_GroupBase*>::const_iterator g = grps.begin();
+      for ( ; g != grps.end() && !myGroup; ++g )
+        if ( *g && myStoreName == (*g)->GetStoreName() )
+          myGroup = *g;
+    }
+  }
+}
+
+bool BelongToMeshGroup::IsSatisfy( long theElementId )
+{
+  return myGroup ? myGroup->Contains( theElementId ) : false;
+}
+
+SMDSAbs_ElementType BelongToMeshGroup::GetType() const
+{
+  return myGroup ? myGroup->GetType() : SMDSAbs_All;
+}
 
 /*
-   ElementsOnSurface
+  ElementsOnSurface
 */
 
 ElementsOnSurface::ElementsOnSurface()
index 7c01c4b281911567b393eb4368b860fe9f588a55..cf3a7cd98ecad86b60dacdc43dc85ba96159f380 100644 (file)
@@ -54,6 +54,7 @@ class SMDS_Mesh;
 
 class SMESHDS_Mesh;
 class SMESHDS_SubMesh;
+class SMESHDS_GroupBase;
 
 class gp_Pnt;
 
@@ -763,8 +764,8 @@ namespace SMESH{
                               TMapOfLink&            theNonManifold,
                               SMDS_MeshFace*         theNextFace ) const;
 
-     void     getFacesByLink( const Link& theLink,
-                              TVectorOfFacePtr& theFaces ) const;
+      void     getFacesByLink( const Link& theLink,
+                               TVectorOfFacePtr& theFaces ) const;
 
     private:
       const SMDS_Mesh*      myMesh;
@@ -779,6 +780,27 @@ namespace SMESH{
     };
     typedef boost::shared_ptr<ManifoldPart> ManifoldPartPtr;
 
+    /*
+      Class       : BelongToMeshGroup
+      Description : Verify whether a mesh element is included into a mesh group
+    */
+    class SMESHCONTROLS_EXPORT BelongToMeshGroup : public virtual Predicate
+    {
+    public:
+      BelongToMeshGroup();
+      virtual void SetMesh( const SMDS_Mesh* theMesh );
+      virtual bool IsSatisfy( long theElementId );
+      virtual SMDSAbs_ElementType GetType() const;
+
+      void SetGroup( SMESHDS_GroupBase* g );
+      void SetStoreName( const std::string& sn );
+      const SMESHDS_GroupBase* GetGroup() const { return myGroup; }
+
+    private:
+      SMESHDS_GroupBase* myGroup;
+      std::string        myStoreName;
+    };
+    typedef boost::shared_ptr<BelongToMeshGroup> BelongToMeshGroupPtr;
 
     /*
       Class       : ElementsOnSurface
@@ -809,7 +831,6 @@ namespace SMESH{
       TMeshModifTracer      myMeshModifTracer;
       TColStd_MapOfInteger  myIds;
       SMDSAbs_ElementType   myType;
-      //Handle(Geom_Surface)  mySurf;
       TopoDS_Face           mySurf;
       double                myToler;
       bool                  myUseBoundaries;
index 5b741437af1af846076d28658744094d15e260c2..ee7c742f53879cf159d658df899c7b175a50ae38 100644 (file)
@@ -48,7 +48,7 @@ namespace SMESH{
 
     /*
       Class       : Functor
-      Description : Root of all Functors
+      Description : Root of all Functors defined in ../Controls/SMESH_ControlsDef.hxx
     */
     class SMESHCONTROLS_EXPORT Functor
     {
index 891b41ca5eee8c96d3a58dcafa1a95eca29f44de..c1b80e0d0c439c753f010e64f849f781f381d688 100755 (executable)
 
 #include <LightApp_Application.h>
 #include <LightApp_SelectionMgr.h>
-#include <SalomeApp_Tools.h>
-#include <SalomeApp_Study.h>
-#include <SalomeApp_IntSpinBox.h>
+#include <SalomeApp_Application.h>
 #include <SalomeApp_DoubleSpinBox.h>
+#include <SalomeApp_IntSpinBox.h>
+#include <SalomeApp_Study.h>
+#include <SalomeApp_Tools.h>
 
 #include <SALOME_ListIO.hxx>
 
@@ -1134,6 +1135,7 @@ bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType)
         errMsg = tr( "GROUPCOLOR_ERROR" );
     }
     else if (aCriterion == SMESH::FT_RangeOfIds ||
+             aCriterion == SMESH::FT_BelongToMeshGroup ||
              aCriterion == SMESH::FT_BelongToGeom ||
              aCriterion == SMESH::FT_BelongToPlane ||
              aCriterion == SMESH::FT_BelongToCylinder ||
@@ -1283,6 +1285,7 @@ void SMESHGUI_FilterTable::GetCriterion (const int                 theRow,
     }
   }
   else if ( aCriterionType != SMESH::FT_RangeOfIds &&
+            aCriterionType != SMESH::FT_BelongToMeshGroup &&
             aCriterionType != SMESH::FT_BelongToGeom &&
             aCriterionType != SMESH::FT_BelongToPlane &&
             aCriterionType != SMESH::FT_BelongToCylinder &&
@@ -1382,6 +1385,7 @@ void SMESHGUI_FilterTable::SetCriterion (const int                       theRow,
     }
   }
   else if (theCriterion.Type != SMESH::FT_RangeOfIds &&
+           theCriterion.Type != SMESH::FT_BelongToMeshGroup &&
            theCriterion.Type != SMESH::FT_BelongToGeom &&
            theCriterion.Type != SMESH::FT_BelongToPlane &&
            theCriterion.Type != SMESH::FT_BelongToCylinder &&
@@ -1398,6 +1402,7 @@ void SMESHGUI_FilterTable::SetCriterion (const int                       theRow,
            theCriterion.Type != SMESH::FT_OverConstrainedVolume &&
            theCriterion.Type != SMESH::FT_LinearOrQuadratic)
   {
+    // Numberic criterion
     aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15));
   }
   else
@@ -1813,13 +1818,15 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con
   case SMESH::FT_Length:
   case SMESH::FT_Length2D: anIsDoubleCriterion = true; break;
 
+  case SMESH::FT_BelongToMeshGroup: break;
+
   case SMESH::FT_BelongToGeom:
   case SMESH::FT_BelongToPlane:
   case SMESH::FT_BelongToCylinder:
   case SMESH::FT_BelongToGenSurface:
-  case SMESH::FT_LyingOnGeom: nbCompareSigns = 1; isThresholdEditable = true; break;
+  case SMESH::FT_LyingOnGeom: nbCompareSigns = 0; isThresholdEditable = true; break;
 
-  case SMESH::FT_RangeOfIds: nbCompareSigns = 1; isThresholdEditable = true; break;
+  case SMESH::FT_RangeOfIds: nbCompareSigns = 0; isThresholdEditable = true; break;
 
   case SMESH::FT_BadOrientedVolume:
   case SMESH::FT_BareBorderVolume:
@@ -2162,6 +2169,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     if (aCriteria.isEmpty())
     {
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2183,6 +2191,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
       aCriteria[ SMESH::FT_MultiConnection    ] = tr("MULTI_BORDERS");
       aCriteria[ SMESH::FT_Length             ] = tr("LENGTH");
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2211,6 +2220,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
       aCriteria[ SMESH::FT_MaxElementLength2D ] = tr("MAX_ELEMENT_LENGTH_2D");
       aCriteria[ SMESH::FT_FreeEdges          ] = tr("FREE_EDGES");
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2238,6 +2248,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     {
       aCriteria[ SMESH::FT_AspectRatio3D        ] = tr("ASPECT_RATIO_3D");
       aCriteria[ SMESH::FT_RangeOfIds           ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup    ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom         ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_LyingOnGeom          ] = tr("LYING_ON_GEOM");
       aCriteria[ SMESH::FT_BadOrientedVolume    ] = tr("BAD_ORIENTED_VOLUME");
@@ -2260,6 +2271,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     if (aCriteria.isEmpty())
     {
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2276,6 +2288,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     {
       aCriteria[ SMESH::FT_BallDiameter       ] = tr("BALL_DIAMETER");
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2291,6 +2304,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     if (aCriteria.isEmpty())
     {
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
@@ -2306,6 +2320,7 @@ const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType)
     if (aCriteria.isEmpty())
     {
       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
+      aCriteria[ SMESH::FT_BelongToMeshGroup  ] = tr("BELONG_TO_MESH_GROUP");
       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
       aCriteria[ SMESH::FT_LyingOnGeom        ] = tr("LYING_ON_GEOM");
       aCriteria[ SMESH::FT_LinearOrQuadratic  ] = tr("LINEAR");
@@ -2869,6 +2884,7 @@ void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes, const bool setInViewe
   mySourceWg  = 0;
   myTypes     = theTypes;
   myMesh      = SMESH::SMESH_Mesh::_nil();
+  myGroup     = SMESH::SMESH_GroupOnFilter::_nil();
   myIObjects.Clear();
   myIsSelectionChanged = false;
   myToRestoreSelMode = false;
@@ -3147,8 +3163,7 @@ bool SMESHGUI_FilterDlg::isValid() const
       if (aType == SMESH::FT_BelongToCylinder ||
           aType == SMESH::FT_BelongToPlane    ||
           aType == SMESH::FT_BelongToGenSurface ) {
-        CORBA::Object_var anObject = SMESH::SObjectToObject(aList[ 0 ]);
-        //GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(aList[ 0 ]->GetObject());
+        CORBA::Object_var     anObject = SMESH::SObjectToObject(aList[ 0 ]);
         GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(anObject);
         if (!aGeomObj->_is_nil()) {
           TopoDS_Shape aFace;
@@ -3252,6 +3267,15 @@ void SMESHGUI_FilterDlg::SetMesh (SMESH::SMESH_Mesh_var theMesh)
   myButtons[BTN_Apply]->setEnabled(isEnable);
 }
 
+//=======================================================================
+// name    : SMESHGUI_FilterDlg::SetGroup
+// Purpose : Set a group being edited
+//=======================================================================
+void SMESHGUI_FilterDlg::SetGroup(SMESH::SMESH_GroupOnFilter_var group)
+{
+  myGroup = group;
+}
+
 //=======================================================================
 // name    : SMESHGUI_FilterDlg::SetSelection
 // Purpose : Get filtered ids
@@ -3659,10 +3683,10 @@ void SMESHGUI_FilterDlg::onSelectionDone()
 
   const int type = myTable->GetCriterionType(aRow);
   QList<int> types; 
-  types << SMESH::FT_BelongToGeom     << SMESH::FT_BelongToPlane 
-        << SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
-        << SMESH::FT_LyingOnGeom      << SMESH::FT_CoplanarFaces
-        << SMESH::FT_ConnectedElements;
+  types << SMESH::FT_BelongToGeom      << SMESH::FT_BelongToPlane 
+        << SMESH::FT_BelongToCylinder  << SMESH::FT_BelongToGenSurface
+        << SMESH::FT_LyingOnGeom       << SMESH::FT_CoplanarFaces
+        << SMESH::FT_ConnectedElements << SMESH::FT_BelongToMeshGroup;
   if ( !types.contains( type ))
     return;
 
@@ -3694,6 +3718,29 @@ void SMESHGUI_FilterDlg::onSelectionDone()
       }
       break;
     }
+  case SMESH::FT_BelongToMeshGroup: // get a group name and IOR
+    {
+      SMESH::SMESH_GroupBase_var grp = SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(anIO);
+      if ( !grp->_is_nil() )
+      {
+        if ( !myMesh->_is_nil() )
+        {
+          SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
+          if ( ! myMesh->_is_equivalent( mesh ))
+            return;
+        }
+        if ( !myGroup->_is_nil() && myGroup->IsInDependency( grp ))
+          return; // avoid cyclic dependencies between Groups on Filter
+
+        SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
+          ( SUIT_Session::session()->activeApplication() );
+        if( !app ) return;
+        CORBA::String_var IOR = app->orb()->object_to_string( grp );
+
+        myTable->SetThreshold(aRow, SMESH::toQStr( grp->GetName() ));
+        myTable->SetID       (aRow, IOR.in() );
+      }
+    }
   default: // get a GEOM object
     {
       GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
@@ -3785,6 +3832,23 @@ void SMESHGUI_FilterDlg::updateSelection()
     myIsSelectionChanged = true;
 
   }
+  else if ( aCriterionType == SMESH::FT_BelongToMeshGroup )
+  {
+    SMESH_TypeFilter* typeFilter = 0;
+    switch ( myTable->GetType() )
+    {
+    case SMESH::NODE   : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_NODE   ); break;
+    case SMESH::ELEM0D : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_0D     ); break;
+    case SMESH::BALL   : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_BALL   ); break;
+    case SMESH::EDGE   : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_EDGE   ); break;
+    case SMESH::FACE   : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_FACE   ); break;
+    case SMESH::VOLUME : typeFilter = new SMESH_TypeFilter( SMESH::GROUP_VOLUME ); break;
+    case SMESH::ALL    : typeFilter = new SMESH_TypeFilter( SMESH::GROUP        ); break;
+    default            : typeFilter = 0;
+    }
+    if ( typeFilter )
+      mySelectionMgr->installFilter( typeFilter );
+  }
   else if ( aCriterionType == SMESH::FT_ConnectedElements )
   {
     QList<SUIT_SelectionFilter*> fList;
index 0f14915ae3618b7119097d41a5508eddf7ad41fa..55d854c17162dc532f8a2c16d9d09d2ce4c79b9b 100755 (executable)
@@ -228,6 +228,7 @@ public:
 
   void                      SetSelection();
   void                      SetMesh (SMESH::SMESH_Mesh_var);
+  void                      SetGroup (SMESH::SMESH_GroupOnFilter_var);
   void                      SetSourceWg( QWidget*, const bool initOnApply = true );
   void                      SetEnabled( bool setInViewer, bool diffSources );
 
@@ -297,6 +298,7 @@ private:
   LightApp_SelectionMgr*    mySelectionMgr;
   SVTK_Selector*            mySelector;
   SMESH::SMESH_Mesh_var     myMesh;
+  SMESH::SMESH_GroupOnFilter_var myGroup;
   bool                      myInitSourceWgOnApply;
   bool                      myInsertEnabled;
   bool                      myDiffSourcesEnabled;
index 2fc4c48fd58947ca399c36f6ebac37713fc73e97..c4b0465de691d71a1e70b2dec1ff5abfa3b64e97 100644 (file)
@@ -1205,11 +1205,11 @@ void SMESHGUI_FilterLibraryDlg::onSelectionDone()
     return;
 
   const int type = myTable->GetCriterionType(aRow);
-  QList<int> types; 
-  types << SMESH::FT_BelongToGeom     << SMESH::FT_BelongToPlane 
-        << SMESH::FT_BelongToCylinder << SMESH::FT_BelongToGenSurface
-        << SMESH::FT_LyingOnGeom      << SMESH::FT_CoplanarFaces
-        << SMESH::FT_ConnectedElements;
+  QList<int> types;
+  types << SMESH::FT_BelongToGeom      << SMESH::FT_BelongToPlane 
+        << SMESH::FT_BelongToCylinder  << SMESH::FT_BelongToGenSurface
+        << SMESH::FT_LyingOnGeom       << SMESH::FT_CoplanarFaces
+        << SMESH::FT_ConnectedElements << SMESH::FT_BelongToMeshGroup;
   if ( !types.contains( type ))
     return;
 
@@ -1241,6 +1241,10 @@ void SMESHGUI_FilterLibraryDlg::onSelectionDone()
       }
       break;
     }
+  case SMESH::FT_BelongToMeshGroup: // get a group name and IOR
+    {
+      myTable->SetThreshold(aRow, anIO->getName() );
+    }
   default: // get a GEOM object
     {
       GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
index 9445167a443eb3c3f132d9bf5233b30585c821e1..2a1c5c49baafbee763edda14fe3ac4798f1028d1 100644 (file)
@@ -1197,7 +1197,10 @@ bool SMESHGUI_GroupDlg::onApply()
           }
           // update a visible group accoding to a changed contents
           if ( !isConversion && anActor->GetVisibility() )
+          {
             SMESH::Update( anIO, true );
+            SMESH::RepaintCurrentView();
+          }
         }
       }
     }
@@ -1762,10 +1765,10 @@ void SMESHGUI_GroupDlg::setFilters()
   myFilterDlg->SetEnabled( /*setInViewer=*/isStandalone,
                            /*diffSources=*/isStandalone );
   myFilterDlg->SetMesh( myMesh );
+  myFilterDlg->SetGroup( myGroupOnFilter );
   myFilterDlg->SetSelection();
   myFilterDlg->SetSourceWg( myElements, false );
 
-
   myFilterDlg->show();
 }
 
index eb4df435d312154a3500d20cdf4706953964be3b..bcc289cc0763792680d075b5819b539c9d7af37d 100644 (file)
 #include "SMESHGUI_VTKUtils.h"
 
 #include "SMESHGUI.h"
-#include "SMESHGUI_Utils.h"
 #include "SMESHGUI_Filter.h"
+#include "SMESHGUI_Utils.h"
+#include "SMDS_Mesh.hxx"
+#include "SMESH_Actor.h"
+#include "SMESH_ActorUtils.h"
+#include "SMESH_CellLabelActor.h"
 #include "SMESH_ControlsDef.hxx"
-
-#include <SMESH_Actor.h>
-#include <SMESH_ActorUtils.h>
 #include "SMESH_NodeLabelActor.h"
-#include "SMESH_CellLabelActor.h"
-#include <SMESH_ObjectDef.h>
-#include <SMDS_Mesh.hxx>
+#include "SMESH_ObjectDef.h"
 
 // SALOME GUI includes
 #include <SUIT_Desktop.h>
index ee06a2eb4eca63665aa1f50fb00953f6332acba0..28c62a0fe86e60c85a5eba130368f3832b9dd3cd 100644 (file)
@@ -5421,6 +5421,10 @@ Please check input data and try again</translation>
         <source>OVER_CONSTRAINED_FACE</source>
         <translation>Over-constrained faces</translation>
     </message>
+    <message>
+        <source>BELONG_TO_MESH_GROUP</source>
+        <translation>Belong to Mesh Group</translation>
+    </message>
     <message>
         <source>BELONG_TO_CYLINDER</source>
         <translation>Belong to Cylinder</translation>
index dd885752eb39327f51f2948220fc4a60258563f2..20fea4abc1be928ac5d1887e098bc6f982a160a5 100644 (file)
@@ -423,6 +423,7 @@ namespace SMESH
       case FT_MultiConnection2D:     myStream<< "aMultiConnection2D";     break;
       case FT_Length:                myStream<< "aLength";                break;
       case FT_Length2D:              myStream<< "aLength2D";              break;
+      case FT_BelongToMeshGroup:     myStream<< "aBelongToMeshGroup";     break;
       case FT_BelongToGeom:          myStream<< "aBelongToGeom";          break;
       case FT_BelongToPlane:         myStream<< "aBelongToPlane";         break;
       case FT_BelongToCylinder:      myStream<< "aBelongToCylinder";      break;
index 1165cc93fd1875ec1bacde531c12c92a77d1538b..7dc847a3e2db143ebc48b73e5011119816c9c532 100644 (file)
@@ -31,6 +31,7 @@
 #include "SMDS_Mesh.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
+#include "SMESHDS_GroupBase.hxx"
 #include "SMESHDS_Mesh.hxx"
 #include "SMESH_Gen_i.hxx"
 #include "SMESH_Group_i.hxx"
@@ -722,6 +723,108 @@ FunctorType OverConstrainedFace_i::GetFunctorType()
   return SMESH::FT_OverConstrainedFace;
 }
 
+/*
+  Class       : BelongToMeshGroup_i
+  Description : Verify whether a mesh element is included into a mesh group
+*/
+BelongToMeshGroup_i::BelongToMeshGroup_i()
+{
+  myBelongToMeshGroup = Controls::BelongToMeshGroupPtr( new Controls::BelongToMeshGroup() );
+  myFunctorPtr = myPredicatePtr = myBelongToMeshGroup;
+}
+
+BelongToMeshGroup_i::~BelongToMeshGroup_i()
+{
+  SetGroup( SMESH::SMESH_GroupBase::_nil() );
+}
+
+void BelongToMeshGroup_i::SetGroup( SMESH::SMESH_GroupBase_ptr theGroup )
+{
+  if ( myGroup->_is_equivalent( theGroup ))
+    return;
+
+  if ( ! myGroup->_is_nil() )
+    myGroup->UnRegister();
+
+  myGroup = SMESH_GroupBase::_duplicate( theGroup );
+
+  myBelongToMeshGroup->SetGroup( 0 );
+  if ( SMESH_GroupBase_i* gr_i = SMESH::DownCast< SMESH_GroupBase_i* >( myGroup ))
+  {
+    myBelongToMeshGroup->SetGroup( gr_i->GetGroupDS() );
+    myGroup->Register();
+  }
+}
+
+void BelongToMeshGroup_i::SetGroupID( const char* theID ) // IOR or StoreName
+{
+  myID = theID;
+  if ( strncmp( "IOR:", myID.c_str(), 4 ) == 0 ) // transient mode, no GUI
+  {
+    CORBA::Object_var obj = SMESH_Gen_i::GetORB()->string_to_object( myID.c_str() );
+    SetGroup( SMESH::SMESH_GroupBase::_narrow( obj ));
+  }
+  else if ( strncmp( ":0", myID.c_str(), 2 ) == 0 ) // transient mode + GUI
+  {
+    SMESH_Gen_i* aSMESHGen     = SMESH_Gen_i::GetSMESHGen();
+    SALOMEDS::Study_var aStudy = aSMESHGen->GetCurrentStudy();
+    if ( !aStudy->_is_nil() ) {
+      SALOMEDS::SObject_wrap aSObj = aStudy->FindObjectID( myID.c_str() );
+      if ( !aSObj->_is_nil() ) {
+        CORBA::Object_var obj = aSObj->GetObject();
+        SetGroup( SMESH::SMESH_GroupBase::_narrow( obj ));
+      }
+    }
+  }
+  else if ( !myID.empty() ) // persistent mode
+  {
+    myBelongToMeshGroup->SetStoreName( myID );
+  }
+}
+
+std::string BelongToMeshGroup_i::GetGroupID()
+{
+  if ( myGroup->_is_nil() )
+    SMESH::SMESH_GroupBase_var( GetGroup() );
+
+  if ( !myGroup->_is_nil() )
+    myID = SMESH_Gen_i::GetORB()->object_to_string( myGroup );
+
+  return myID;
+}
+
+SMESH::SMESH_GroupBase_ptr BelongToMeshGroup_i::GetGroup()
+{
+  if ( myGroup->_is_nil() && myBelongToMeshGroup->GetGroup() )
+  {
+    // search for a group in a current study
+    SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
+    if ( StudyContext*  sc = aSMESHGen->GetCurrentStudyContext() )
+    {
+      int id = 1;
+      std::string ior;
+      while (true)
+      {
+        ior = sc->getIORbyId( id++ );
+        if ( ior.empty() ) break;
+        CORBA::Object_var obj = aSMESHGen->GetORB()->string_to_object( ior.c_str() );
+        if ( SMESH_GroupBase_i* g_i = SMESH::DownCast<SMESH_GroupBase_i*>( obj ))
+          if ( g_i->GetGroupDS() == myBelongToMeshGroup->GetGroup() )
+          {
+            SetGroup( g_i->_this() );
+            break;
+          }
+      }
+    }
+  }
+  return SMESH::SMESH_GroupBase::_duplicate( myGroup );
+}
+
+FunctorType BelongToMeshGroup_i::GetFunctorType()
+{
+  return SMESH::FT_BelongToMeshGroup;
+}
+
 /*
   Class       : BelongToGeom_i
   Description : Predicate for selection on geometrical support
@@ -1772,6 +1875,7 @@ Predicate_i* LogicalNOT_i::GetPredicate_i()
 }
 
 
+
 /*
   Class       : LogicalBinary_i
   Description : Base class for binary logical predicate
@@ -2023,6 +2127,14 @@ BallDiameter_ptr FilterManager_i::CreateBallDiameter()
   return anObj._retn();
 }
 
+BelongToMeshGroup_ptr FilterManager_i::CreateBelongToMeshGroup()
+{
+  SMESH::BelongToMeshGroup_i* aServant = new SMESH::BelongToMeshGroup_i();
+  SMESH::BelongToMeshGroup_var anObj = aServant->_this();
+  TPythonDump()<<aServant<<" = "<<this<<".CreateBelongToMeshGroup()";
+  return anObj._retn();
+}
+
 BelongToGeom_ptr FilterManager_i::CreateBelongToGeom()
 {
   SMESH::BelongToGeom_i* aServant = new SMESH::BelongToGeom_i();
@@ -2339,7 +2451,8 @@ Filter_i::~Filter_i()
   if(!CORBA::is_nil(myMesh))
     myMesh->UnRegister();
 
-  //TPythonDump()<<this<<".UnRegister()";
+  myPredicate = 0;
+  FindBaseObjects();
 }
 
 //=======================================================================
@@ -2361,9 +2474,7 @@ void Filter_i::SetPredicate( Predicate_ptr thePredicate )
       myPredicate->GetPredicate()->SetMesh( aMesh );
     TPythonDump()<<this<<".SetPredicate("<<myPredicate<<")";
   }
-  std::list<TPredicateChangeWaiter*>::iterator i = myWaiters.begin();
-  for ( ; i != myWaiters.end(); ++i )
-    (*i)->PredicateChanged();
+  NotifyerAndWaiter::Modified();
 }
 
 //=======================================================================
@@ -2550,28 +2661,35 @@ SALOMEDS::TMPFile* Filter_i::GetVtkUgStream()
   SALOMEDS::TMPFile_var SeqFile;
   return SeqFile._retn();
 }
-
-//================================================================================
-/*!
- * \brief Stores an object to be notified on change of predicate
- */
-//================================================================================
-
-void Filter_i::AddWaiter( TPredicateChangeWaiter* waiter )
+//=======================================================================
+// name    : getCriteria
+// Purpose : Retrieve criterions from predicate
+//=======================================================================
+static inline void getPrediacates( Predicate_i*                thePred,
+                                   std::vector<Predicate_i*> & thePredVec )
 {
-  if ( waiter )
-    myWaiters.push_back( waiter );
-}
-
-//================================================================================
-/*!
- * \brief Removes an object to be notified on change of predicate
- */
-//================================================================================
+  const int aFType = thePred->GetFunctorType();
 
-void Filter_i::RemoveWaiter( TPredicateChangeWaiter* waiter )
-{
-  myWaiters.remove( waiter );
+  switch ( aFType )
+  {
+  case FT_LogicalNOT:
+  {
+    Predicate_i* aPred = ( dynamic_cast<LogicalNOT_i*>( thePred ) )->GetPredicate_i();
+    getPrediacates( aPred, thePredVec );
+    break;
+  }
+  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();
+    getPrediacates( aPred1, thePredVec );
+    getPrediacates( aPred2, thePredVec );
+    break;
+   }
+  default:;
+  }
+  thePredVec.push_back( thePred );
 }
 
 //=======================================================================
@@ -2581,7 +2699,7 @@ void Filter_i::RemoveWaiter( TPredicateChangeWaiter* waiter )
 static inline bool getCriteria( Predicate_i*                thePred,
                                 SMESH::Filter::Criteria_out theCriteria )
 {
-  int aFType = thePred->GetFunctorType();
+  const int aFType = thePred->GetFunctorType();
 
   switch ( aFType )
   {
@@ -2635,6 +2753,17 @@ static inline bool getCriteria( Predicate_i*                thePred,
     {
       return true;
     }
+  case FT_BelongToMeshGroup:
+    {
+      BelongToMeshGroup_i* aPred = dynamic_cast<BelongToMeshGroup_i*>( thePred );
+      SMESH::SMESH_GroupBase_var grp = aPred->GetGroup();
+      if ( !grp->_is_nil() )
+      {
+        theCriteria[ i ].ThresholdStr = grp->GetName();
+        theCriteria[ i ].ThresholdID  = aPred->GetGroupID().c_str();
+      }
+      return true;
+    }
   case FT_BelongToGeom:
     {
       BelongToGeom_i* aPred = dynamic_cast<BelongToGeom_i*>( thePred );
@@ -2873,6 +3002,13 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria
       case SMESH::FT_EqualVolumes:
         aPredicate = aFilterMgr->CreateEqualVolumes();
         break;
+      case SMESH::FT_BelongToMeshGroup:
+        {
+          SMESH::BelongToMeshGroup_ptr tmpPred = aFilterMgr->CreateBelongToMeshGroup();
+          tmpPred->SetGroupID( aThresholdID );
+          aPredicate = tmpPred;
+        }
+        break;
       case SMESH::FT_BelongToGeom:
         {
           SMESH::BelongToGeom_ptr tmpPred = aFilterMgr->CreateBelongToGeom();
@@ -3136,6 +3272,75 @@ Predicate_ptr Filter_i::GetPredicate()
   }
 }
 
+//================================================================================
+/*!
+ * \brief Find groups it depends on
+ */
+//================================================================================
+
+void Filter_i::FindBaseObjects()
+{
+  // release current groups
+  for ( size_t i = 0; i < myBaseGroups.size(); ++i )
+    if ( myBaseGroups[i] )
+    {
+      myBaseGroups[i]->RemoveModifWaiter( this );
+      myBaseGroups[i]->UnRegister();
+    }
+
+  // remember new groups
+  myBaseGroups.clear();
+  if ( myPredicate )
+  {
+    std::vector<Predicate_i*> predicates;
+    getPrediacates( myPredicate, predicates );
+    for ( size_t i = 0; i < predicates.size(); ++i )
+      if ( BelongToMeshGroup_i* bmg = dynamic_cast< BelongToMeshGroup_i* >( predicates[i] ))
+      {
+        SMESH::SMESH_GroupBase_var g = bmg->GetGroup();
+        SMESH_GroupBase_i* g_i = SMESH::DownCast< SMESH_GroupBase_i*>( g );
+        if ( g_i )
+        {
+          g_i->AddModifWaiter( this );
+          g_i->Register();
+          myBaseGroups.push_back( g_i );
+        }
+      }
+  }
+}
+
+//================================================================================
+/*!
+ * \brief When notified on removal of myBaseGroups[i], remove a reference to a
+ *        group from a predicate
+ */
+//================================================================================
+
+void Filter_i::OnBaseObjModified(NotifyerAndWaiter* group, bool removed)
+{
+  if ( !removed )
+    return; // a GroupOnFilter holding this filter is notified automatically
+
+  if ( myPredicate )
+  {
+    std::vector<Predicate_i*> predicates;
+    getPrediacates( myPredicate, predicates );
+    for ( size_t i = 0; i < predicates.size(); ++i )
+      if ( BelongToMeshGroup_i* bmg = dynamic_cast< BelongToMeshGroup_i* >( predicates[i] ))
+      {
+        SMESH::SMESH_GroupBase_var g = bmg->GetGroup();
+        SMESH_GroupBase_i* g_i = SMESH::DownCast< SMESH_GroupBase_i*>( g );
+        if ( g_i == group )
+        {
+          bmg->SetGroup( SMESH::SMESH_GroupBase::_nil() );
+          bmg->SetGroupID( "" );
+        }
+      }
+  }
+
+  FindBaseObjects(); // release and update myBaseGroups;
+}
+
 /*
                             FILTER LIBRARY
 */
@@ -3195,50 +3400,51 @@ static inline LDOMString toString( CORBA::Long theType )
 {
   switch ( theType )
   {
-    case FT_AspectRatio     : return "Aspect ratio";
-    case FT_Warping         : return "Warping";
-    case FT_MinimumAngle    : return "Minimum angle";
-    case FT_Taper           : return "Taper";
-    case FT_Skew            : return "Skew";
-    case FT_Area            : return "Area";
-    case FT_Volume3D        : return "Volume3D";
-    case FT_MaxElementLength2D: return "Max element length 2D";
-    case FT_MaxElementLength3D: return "Max element length 3D";
-    case FT_BelongToGeom    : return "Belong to Geom";
-    case FT_BelongToPlane   : return "Belong to Plane";
-    case FT_BelongToCylinder: return "Belong to Cylinder";
-    case FT_BelongToGenSurface: return "Belong to Generic Surface";
-    case FT_LyingOnGeom     : return "Lying on Geom";
-    case FT_BadOrientedVolume:return "Bad Oriented Volume";
-    case FT_BareBorderVolume: return "Volumes with bare border";
-    case FT_BareBorderFace  : return "Faces with bare border";
-    case FT_OverConstrainedVolume: return "Over-constrained Volumes";
-    case FT_OverConstrainedFace  : return "Over-constrained Faces";
-    case FT_RangeOfIds      : return "Range of IDs";
-    case FT_FreeBorders     : return "Free borders";
-    case FT_FreeEdges       : return "Free edges";
-    case FT_FreeFaces       : return "Free faces";
-    case FT_FreeNodes       : return "Free nodes";
-    case FT_EqualNodes      : return "Equal nodes";
-    case FT_EqualEdges      : return "Equal edges";
-    case FT_EqualFaces      : return "Equal faces";
-    case FT_EqualVolumes    : return "Equal volumes";
-    case FT_MultiConnection : return "Borders at multi-connections";
-    case FT_MultiConnection2D:return "Borders at multi-connections 2D";
-    case FT_Length          : return "Length";
-    case FT_Length2D        : return "Length 2D";
-    case FT_LessThan        : return "Less than";
-    case FT_MoreThan        : return "More than";
-    case FT_EqualTo         : return "Equal to";
-    case FT_LogicalNOT      : return "Not";
-    case FT_LogicalAND      : return "And";
-    case FT_LogicalOR       : return "Or";
-    case FT_GroupColor      : return "Color of Group";
-    case FT_LinearOrQuadratic : return "Linear or Quadratic";
-    case FT_ElemGeomType    : return "Element geomtry type";
-    case FT_EntityType      : return "Entity type";
-    case FT_Undefined       : return "";
-    default                 : return "";
+    case FT_AspectRatio           : return "Aspect ratio";
+    case FT_Warping               : return "Warping";
+    case FT_MinimumAngle          : return "Minimum angle";
+    case FT_Taper                 : return "Taper";
+    case FT_Skew                  : return "Skew";
+    case FT_Area                  : return "Area";
+    case FT_Volume3D              : return "Volume3D";
+    case FT_MaxElementLength2D    : return "Max element length 2D";
+    case FT_MaxElementLength3D    : return "Max element length 3D";
+    case FT_BelongToMeshGroup     : return "Belong to Mesh Group";
+    case FT_BelongToGeom          : return "Belong to Geom";
+    case FT_BelongToPlane         : return "Belong to Plane";
+    case FT_BelongToCylinder      : return "Belong to Cylinder";
+    case FT_BelongToGenSurface    : return "Belong to Generic Surface";
+    case FT_LyingOnGeom           : return "Lying on Geom";
+    case FT_BadOrientedVolume     : return "Bad Oriented Volume";
+    case FT_BareBorderVolume      : return "Volumes with bare border";
+    case FT_BareBorderFace        : return "Faces with bare border";
+    case FT_OverConstrainedVolume : return "Over-constrained Volumes";
+    case FT_OverConstrainedFace   : return "Over-constrained Faces";
+    case FT_RangeOfIds            : return "Range of IDs";
+    case FT_FreeBorders           : return "Free borders";
+    case FT_FreeEdges             : return "Free edges";
+    case FT_FreeFaces             : return "Free faces";
+    case FT_FreeNodes             : return "Free nodes";
+    case FT_EqualNodes            : return "Equal nodes";
+    case FT_EqualEdges            : return "Equal edges";
+    case FT_EqualFaces            : return "Equal faces";
+    case FT_EqualVolumes          : return "Equal volumes";
+    case FT_MultiConnection       : return "Borders at multi-connections";
+    case FT_MultiConnection2D     :return "Borders at multi-connections 2D";
+    case FT_Length                : return "Length";
+    case FT_Length2D              : return "Length 2D";
+    case FT_LessThan              : return "Less than";
+    case FT_MoreThan              : return "More than";
+    case FT_EqualTo               : return "Equal to";
+    case FT_LogicalNOT            : return "Not";
+    case FT_LogicalAND            : return "And";
+    case FT_LogicalOR             : return "Or";
+    case FT_GroupColor            : return "Color of Group";
+    case FT_LinearOrQuadratic     : return "Linear or Quadratic";
+    case FT_ElemGeomType          : return "Element geomtry type";
+    case FT_EntityType            : return "Entity type";
+    case FT_Undefined             : return "";
+    default                       : return "";
   }
 }
 
@@ -3257,6 +3463,7 @@ static inline SMESH::FunctorType toFunctorType( const LDOMString& theStr )
   else if ( theStr.equals( "Volume3D"                     ) ) return FT_Volume3D;
   else if ( theStr.equals( "Max element length 2D"        ) ) return FT_MaxElementLength2D;
   else if ( theStr.equals( "Max element length 3D"        ) ) return FT_MaxElementLength3D;
+  else if ( theStr.equals( "Belong to Mesh Group"         ) ) return FT_BelongToMeshGroup;
   else if ( theStr.equals( "Belong to Geom"               ) ) return FT_BelongToGeom;
   else if ( theStr.equals( "Belong to Plane"              ) ) return FT_BelongToPlane;
   else if ( theStr.equals( "Belong to Cylinder"           ) ) return FT_BelongToCylinder;
@@ -3838,6 +4045,7 @@ static const char** getFunctNames()
     "FT_MultiConnection2D",
     "FT_Length",
     "FT_Length2D",
+    "FT_BelongToMeshGroup",
     "FT_BelongToGeom",
     "FT_BelongToPlane",
     "FT_BelongToCylinder",
@@ -3865,7 +4073,7 @@ static const char** getFunctNames()
     "FT_Undefined"};
 
 #ifdef _DEBUG_
-  // check if functName is complete, compilation failure mains that enum FunctorType changed
+  // check if functName is complete, compilation failure means that enum FunctorType changed
   const int nbFunctors = sizeof(functName) / sizeof(const char*);
   int _assert[( nbFunctors == SMESH::FT_Undefined + 1 ) ? 1 : -1 ];
 #endif
@@ -3905,3 +4113,62 @@ SMESH::FunctorType SMESH::StringToFunctorType(const char* str)
 
   return SMESH::FunctorType( ft );
 }
+
+//================================================================================
+/*!
+ * \brief calls OnBaseObjModified(), if who != this, and myWaiters[i]->Modified(who)
+ */
+//================================================================================
+
+void NotifyerAndWaiter::Modified( bool removed, NotifyerAndWaiter* who )
+{
+  if ( who != 0 && who != this )
+    OnBaseObjModified( who, removed );
+  else
+    who = this;
+
+  std::list<NotifyerAndWaiter*> waiters = myWaiters; // myWaiters can be changed by Modified()
+  std::list<NotifyerAndWaiter*>::iterator i = waiters.begin();
+  for ( ; i != waiters.end(); ++i )
+    (*i)->Modified( removed, who );
+}
+
+//================================================================================
+/*!
+ * \brief Stores an object to be notified on change of predicate
+ */
+//================================================================================
+
+void NotifyerAndWaiter::AddModifWaiter( NotifyerAndWaiter* waiter )
+{
+  if ( waiter )
+    myWaiters.push_back( waiter );
+}
+
+//================================================================================
+/*!
+ * \brief Removes an object to be notified on change of predicate
+ */
+//================================================================================
+
+void NotifyerAndWaiter::RemoveModifWaiter( NotifyerAndWaiter* waiter )
+{
+  myWaiters.remove( waiter );
+}
+
+//================================================================================
+/*!
+ * \brief Checks if a waiter is among myWaiters, maybe nested
+ */
+//================================================================================
+
+bool NotifyerAndWaiter::ContainModifWaiter( NotifyerAndWaiter* waiter )
+{
+  bool is = ( waiter == this );
+
+  std::list<NotifyerAndWaiter*>::iterator w = myWaiters.begin();
+  for ( ; !is && w != myWaiters.end(); ++w )
+    is = (*w)->ContainModifWaiter( waiter );
+
+  return is;
+}
index 1b70ae38836b0d6751326ab20c99cb4d9c9bd9a2..92b1235b42b20837edeaeb36e50a30fe114510a3 100644 (file)
 
 #include <list>
 
+class SMESH_GroupBase_i;
+
+
 namespace SMESH
 {
+  /*!
+   * \brief Object notified on change of base objects and
+   *        notifying dependent objects in its turn.
+   *        This interface is used to track the following dependencies:
+   *        - GroupOnFiler depending on Filter predicates
+   *        - Filter depending on a Group via FT_BelongToMeshGroup predicate 
+   */
+  struct NotifyerAndWaiter
+  {
+    virtual void OnBaseObjModified(NotifyerAndWaiter* obj, bool removed) {};
+    // specific reaction on modification of a base object
+
+    void Modified( bool removed=false, NotifyerAndWaiter* who = 0);
+    // calls OnBaseObjModified(), if who != 0, and myWaiters[i]->Modified(who)
+
+    void AddModifWaiter    ( NotifyerAndWaiter* waiter ); // adds a dependent object to notify
+    void RemoveModifWaiter ( NotifyerAndWaiter* waiter ); // CALL IT when a waiter dies!!!
+    bool ContainModifWaiter( NotifyerAndWaiter* waiter );
+    std::list<NotifyerAndWaiter*> myWaiters;
+  };
   // ================================================================================
   /*
     FUNCTORS
@@ -370,6 +393,28 @@ namespace SMESH
     FunctorType                     GetFunctorType();
   };
 
+  /*
+    Class       : BelongToMeshGroup_i
+    Description : Verify whether a mesh element is included into a mesh group
+  */
+  class SMESH_I_EXPORT BelongToMeshGroup_i: public virtual POA_SMESH::BelongToMeshGroup,
+                                            public virtual Predicate_i
+  {
+    std::string                    myID; // IOR or StoreName
+    SMESH::SMESH_GroupBase_var     myGroup;
+    Controls::BelongToMeshGroupPtr myBelongToMeshGroup;
+  public:
+    BelongToMeshGroup_i();
+    ~BelongToMeshGroup_i();
+    void                       SetGroup( SMESH::SMESH_GroupBase_ptr theGroup );
+    void                       SetGroupID( const char* theID ); // IOR or StoreName
+    SMESH::SMESH_GroupBase_ptr GetGroup();
+
+    std::string                GetGroupID();
+    FunctorType                GetFunctorType();
+    //virtual void               SetMesh( SMESH_Mesh_ptr theMesh );
+  };
+
   /*
     Class       : BelongToGeom_i
     Description : Predicate for selection on geometrical support
@@ -896,7 +941,8 @@ namespace SMESH
     FILTER
   */
   class SMESH_I_EXPORT Filter_i: public virtual POA_SMESH::Filter,
-                                 public virtual SALOME::GenericObj_i
+                                 public virtual SALOME::GenericObj_i,
+                                 public NotifyerAndWaiter
   {
   public:
     Filter_i();
@@ -943,6 +989,12 @@ namespace SMESH
 
     Predicate_i*     GetPredicate_i();
 
+    void FindBaseObjects();
+    // finds groups it depends on
+
+    virtual void OnBaseObjModified(NotifyerAndWaiter* group, bool removed);
+    // notified on change of myBaseGroups[i]
+
     // =========================
     // SMESH_IDSource interface
     // =========================
@@ -953,22 +1005,13 @@ namespace SMESH
     virtual SMESH::SMESH_Mesh_ptr        GetMesh();
     virtual bool                         IsMeshInfoCorrect() { return true; }
     virtual SALOMEDS::TMPFile*           GetVtkUgStream();
-    /*!
-     * \brief Object notified on change of predicate
-     */
-    struct TPredicateChangeWaiter
-    {
-      virtual void PredicateChanged() = 0;
-    };
-    void AddWaiter( TPredicateChangeWaiter* waiter );
-    void RemoveWaiter( TPredicateChangeWaiter* waiter );
 
   private:
     Controls::Filter myFilter;
     Predicate_i*     myPredicate;
     SMESH_Mesh_var   myMesh;
 
-    std::list<TPredicateChangeWaiter*> myWaiters;
+    std::vector< SMESH_GroupBase_i* > myBaseGroups;
   };
   
   
@@ -1036,6 +1079,7 @@ namespace SMESH
     MultiConnection2D_ptr     CreateMultiConnection2D();
     BallDiameter_ptr          CreateBallDiameter();
     
+    BelongToMeshGroup_ptr     CreateBelongToMeshGroup();
     BelongToGeom_ptr          CreateBelongToGeom();
     BelongToPlane_ptr         CreateBelongToPlane();
     BelongToCylinder_ptr      CreateBelongToCylinder();
index 58bbe32f05b0c59e15c62f1b23252fe20e5fdfef..824655a8775c4ecb7d7f2d8052a879a2ed8cf4b0 100644 (file)
@@ -4073,6 +4073,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
 
   list< pair< SMESH_Hypothesis_i*, string > >    hypDataList;
   list< pair< SMESH_Mesh_i*,       HDFgroup* > > meshGroupList;
+  list< SMESH::Filter_var >                      filters;
 
   // get total number of top-level groups
   int aNbGroups = aFile->nInternalObjects();
@@ -4715,6 +4716,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                 if ( strlen( persistStr ) > 0 ) {
                   filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
+                  filters.push_back( filter );
                 }
               }
 
@@ -4761,11 +4763,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
                 aGroupBaseDS->SetColor( aColor );
               }
-
-              // Fill group with contents from MED file
-              // SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
-              // if ( aGrp )
-              //   myReader.GetGroup( aGrp );
             }
           }
           aGroup->CloseOnDisk();
@@ -4824,6 +4821,13 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
     }
 
+    // let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877)
+    list< SMESH::Filter_var >::iterator f = filters.begin();
+    for ( ; f != filters.end(); ++f )
+      if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f ))
+        fi->FindBaseObjects();
+
+
     // close mesh group
     if(aTopGroup)
       aTopGroup->CloseOnDisk();
index 0a955a1facaaadca28f66556760052be13f876be..6218de9f8ba5485d3cd07b398da23c30a280d9bd 100644 (file)
@@ -244,6 +244,21 @@ CORBA::Boolean SMESH_GroupBase_i::IsEmpty()
   return true;
 }
 
+//=============================================================================
+/*
+ * Returns \c true if \c this group depends on the \a other via
+ * FT_BelongToMeshGroup predicate or vice versa
+ */
+//=============================================================================
+
+bool SMESH_GroupBase_i::IsInDependency( SMESH::SMESH_GroupBase_ptr other )
+{
+  if ( NotifyerAndWaiter* nw = SMESH::DownCast< NotifyerAndWaiter* >( other ))
+    return ( nw->ContainModifWaiter( this ) || this->ContainModifWaiter( nw ));
+
+  return false;
+}
+
 //=============================================================================
 /*!
  *  
@@ -264,6 +279,8 @@ void SMESH_Group_i::Clear()
     aGroupDS->Clear();
     return;
   }
+  Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
+
   MESSAGE("attempt to clear a vague group");
 }
 
@@ -308,6 +325,8 @@ CORBA::Long SMESH_Group_i::Add( const SMESH::long_array& theIDs )
       if (aGroupDS->Add(anID))
         nbAdd++;
     }
+    if ( nbAdd )
+      Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
     return nbAdd;
   }
   MESSAGE("attempt to add elements to a vague group");
@@ -338,6 +357,8 @@ CORBA::Long SMESH_Group_i::Remove( const SMESH::long_array& theIDs )
       if (aGroupDS->Remove(anID))
         nbDel++;
     }
+    if ( nbDel )
+      Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
     return nbDel;
   }
   MESSAGE("attempt to remove elements from a vague group");
@@ -355,6 +376,7 @@ typedef bool (SMESHDS_Group::*TFunChangeGroup)(const int);
 CORBA::Long 
 ChangeByPredicate( SMESH::Predicate_i* thePredicate,
                    SMESHDS_GroupBase*  theGroupBase,
+                   NotifyerAndWaiter*  theGroupImpl,
                    TFunChangeGroup     theFun)
 {
   CORBA::Long aNb = 0;
@@ -367,6 +389,8 @@ ChangeByPredicate( SMESH::Predicate_i* thePredicate,
     for(; i < iEnd; i++)
       if((aGroupDS->*theFun)(aSequence[i]))
         aNb++;
+    if ( aNb )
+      theGroupImpl->Modified();
     return aNb;
   }
   return aNb;
@@ -382,7 +406,7 @@ AddByPredicate( SMESH::Predicate_ptr thePredicate )
   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
     TPythonDump() << SMESH::SMESH_Group_var(_this())
                   << ".AddByPredicate( " << aPredicate << " )";
-    return ChangeByPredicate( aPredicate, GetGroupDS(), &SMESHDS_Group::Add );
+    return ChangeByPredicate( aPredicate, GetGroupDS(), this, &SMESHDS_Group::Add );
   }
   return 0;
 }
@@ -397,7 +421,7 @@ RemoveByPredicate( SMESH::Predicate_ptr thePredicate )
   if(SMESH::Predicate_i* aPredicate = SMESH::GetPredicate(thePredicate)){
     TPythonDump() << SMESH::SMESH_Group_var(_this())
                   << ".RemoveByPredicate( " << aPredicate << " )";
-    return ChangeByPredicate(aPredicate,GetGroupDS(),&SMESHDS_Group::Remove);
+    return ChangeByPredicate(aPredicate,GetGroupDS(),this, &SMESHDS_Group::Remove);
   }
   return 0;
 }
@@ -419,12 +443,15 @@ CORBA::Long SMESH_Group_i::AddFrom( SMESH::SMESH_IDSource_ptr theSource )
   // Update Python script
   pd << "nbAdd = " << SMESH::SMESH_Group_var(_this()) << ".AddFrom( " << theSource << " )";
 
-  return prevNb - Size();
+  if ( prevNb != Size() )
+    Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
+
+  return Size() - prevNb;
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
@@ -784,6 +811,7 @@ SMESH_PredicatePtr SMESH_GroupOnFilter_i::GetPredicate( SMESH::Filter_ptr filter
 //================================================================================
 
 void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
+  throw (SALOME::SALOME_Exception)
 {
   if ( myFilter->_is_equivalent( theFilter ))
     return;
@@ -796,17 +824,34 @@ void SMESH_GroupOnFilter_i::SetFilter(SMESH::Filter_ptr theFilter)
 
   myFilter = SMESH::Filter::_duplicate( theFilter );
 
-  if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
-    grDS->SetPredicate( GetPredicate( myFilter ));
+  if ( !myFilter->_is_nil() )
+  {
+    myFilter->Register();
 
-  TPythonDump()<< SMESH::SMESH_GroupOnFilter_var(_this()) <<".SetFilter( "<<theFilter<<" )";
+    if ( SMESH::Filter_i* f = SMESH::DownCast< SMESH::Filter_i* >( myFilter ))
+    {
+      // make filter notify me about change of either a predicate or a base group
+      f->FindBaseObjects();
+
+      if ( f->ContainModifWaiter( this ) ||
+           this->ContainModifWaiter( f ))
+      {
+        SetFilter( SMESH::Filter::_nil() );
+        THROW_SALOME_CORBA_EXCEPTION( "Cyclic dependency between Groups on Filter",
+                                      SALOME::BAD_PARAM );
+      }
+      f->AddModifWaiter( this );
+    }
+    myFilter->SetMesh( SMESH::SMESH_Mesh::_nil() ); // to UnRegister() the mesh
+  }
 
-  if ( myFilter )
+  if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
   {
-    myFilter->SetMesh( SMESH::SMESH_Mesh::_nil() ); // to UnRegister() the mesh
-    myFilter->Register();
-    SMESH::DownCast< SMESH::Filter_i* >( myFilter )->AddWaiter( this );
+    grDS->SetPredicate( GetPredicate( myFilter ));
+    Modified(); // notify dependent Filter with FT_BelongToMeshGroup criterion
   }
+
+  TPythonDump()<< SMESH::SMESH_GroupOnFilter_var(_this()) <<".SetFilter( "<<theFilter<<" )";
 }
 
 //================================================================================
@@ -900,9 +945,17 @@ std::string SMESH_GroupOnFilter_i::FilterToString() const
     result << criteria->length() << SEPAR;
     for ( unsigned i = 0; i < criteria->length(); ++i )
     {
+      SMESH::Filter::Criterion& crit = criteria[ i ];
+
+      if ( SMESH::FunctorType( crit.Type ) == SMESH::FT_BelongToMeshGroup )
+      {
+        CORBA::Object_var obj = SMESH_Gen_i::GetORB()->string_to_object( crit.ThresholdID );
+        if ( SMESH_GroupBase_i * g = SMESH::DownCast< SMESH_GroupBase_i*>( obj ))
+          if ( SMESHDS_GroupBase* gDS = g->GetGroupDS() )
+            crit.ThresholdID = gDS->GetStoreName();
+      }
       // write FunctorType as string but not as number to assure correct
       // persistence if enum FunctorType is modified by insertion in the middle
-      SMESH::Filter::Criterion& crit = criteria[ i ];
       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Type ))    << SEPAR;
       result << SMESH::FunctorTypeToString( SMESH::FunctorType( crit.Compare )) << SEPAR;
       result << crit.Threshold                                                  << SEPAR;
@@ -987,22 +1040,22 @@ SMESH_GroupOnFilter_i::~SMESH_GroupOnFilter_i()
 {
   if ( ! myFilter->_is_nil() )
   {
-    SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveWaiter( this );
+    SMESH::DownCast< SMESH::Filter_i* >( myFilter )->RemoveModifWaiter( this );
     myFilter->UnRegister();
   }
 }
 
 //================================================================================
 /*!
- * \brief Method calleds when a predicate of myFilter changes
+ * \brief Method called when a predicate of myFilter changes
  */
 //================================================================================
 
-void SMESH_GroupOnFilter_i::PredicateChanged()
+void SMESH_GroupOnFilter_i::OnBaseObjModified(NotifyerAndWaiter* filter, bool /*removed*/)
 {
   if ( myPreMeshInfo )
     myPreMeshInfo->FullLoadFromFile();
 
   if ( SMESHDS_GroupOnFilter* grDS = dynamic_cast< SMESHDS_GroupOnFilter*>( GetGroupDS() ))
-    grDS->SetPredicate( GetPredicate( myFilter ));
+    grDS->SetPredicate( GetPredicate( myFilter )); // group resets its cache
 }
index 90ea264a44ff228e8cf61dd76815cde7fff2f853..867ae56ebe54c17466fbe9ed0f95a25edf2f5235 100644 (file)
@@ -48,7 +48,8 @@ class SMESH_PreMeshInfo;
 // ===========
 class SMESH_I_EXPORT SMESH_GroupBase_i:
   public virtual POA_SMESH::SMESH_GroupBase,
-  public virtual SALOME::GenericObj_i
+  public virtual SALOME::GenericObj_i,
+  public SMESH::NotifyerAndWaiter // defined in SMESH_Filter_i.hxx
 {
  public:
   SMESH_GroupBase_i(PortableServer::POA_ptr thePOA,
@@ -100,6 +101,13 @@ class SMESH_I_EXPORT SMESH_GroupBase_i:
    */
   virtual SALOMEDS::TMPFile* GetVtkUgStream();
 
+  /*!
+   * Returns \c true if \c this group depends on the \a other via
+   * FT_BelongToMeshGroup predicate or vice versa
+   */
+  virtual CORBA::Boolean IsInDependency( SMESH::SMESH_GroupBase_ptr other );
+
+
   // Internal C++ interface
   int GetLocalID() const { return myLocalID; }
   SMESH_Mesh_i* GetMeshServant() const { return myMeshServant; }
@@ -173,8 +181,7 @@ class SMESH_I_EXPORT SMESH_GroupOnGeom_i:
 
 class SMESH_I_EXPORT SMESH_GroupOnFilter_i:
   public virtual POA_SMESH::SMESH_GroupOnFilter,
-  public SMESH_GroupBase_i,
-  public SMESH::Filter_i::TPredicateChangeWaiter
+  public SMESH_GroupBase_i
 {
  public:
   SMESH_GroupOnFilter_i( PortableServer::POA_ptr thePOA,
@@ -189,13 +196,13 @@ class SMESH_I_EXPORT SMESH_GroupOnFilter_i:
   static SMESH_PredicatePtr GetPredicate( SMESH::Filter_ptr );
 
   // CORBA interface implementation
-  void SetFilter(SMESH::Filter_ptr theFilter);
+  void SetFilter(SMESH::Filter_ptr theFilter) throw (SALOME::SALOME_Exception);
   SMESH::Filter_ptr GetFilter();
   virtual SMESH::long_array* GetListOfID();
   virtual SMESH::long_array* GetMeshInfo();
 
-  // method of SMESH::Filter_i::TPredicateChangeWaiter
-  virtual void PredicateChanged();
+  // method of SMESH::NotifyerAndWaiter to update self when myFilter changes
+  virtual void OnBaseObjModified(NotifyerAndWaiter* filter, bool);
 
  private:
   SMESH::Filter_var myFilter;
index 7649c27dec4e750f89380c9992c21de2b4c63c64..ffc80579d419bbdf434e67ff1b1732b80f701081 100644 (file)
@@ -1057,6 +1057,7 @@ void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
       builder->RemoveObjectWithChildren( aGroupSO );
     }
   }
+  aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
 
   // Remove the group from SMESH data structures
   removeGroup( aGroup->GetLocalID() );
index 74dddbd464b7979f2b3a790ea9bfd9f3cafc1728..b85912b6b66779ddb3a88c3b1c7be579728ae81a 100644 (file)
@@ -732,7 +732,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
         if CritType in [FT_BelongToGeom,     FT_BelongToPlane, FT_BelongToGenSurface,
                         FT_BelongToCylinder, FT_LyingOnGeom]:
-            # Checks that Threshold is GEOM object
+            # Check that Threshold is GEOM object
             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object):
                 aCriterion.ThresholdStr = GetName(aThreshold)
                 aCriterion.ThresholdID  = aThreshold.GetStudyEntry()
@@ -745,21 +745,28 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             elif isinstance( aThreshold, str ):
                 aCriterion.ThresholdStr = aThreshold
             else:
-                print "Error: The Threshold should be a shape."
-                return None
+                raise TypeError, "The Threshold should be a shape."
             if isinstance(UnaryOp,float):
                 aCriterion.Tolerance = UnaryOp
                 UnaryOp = FT_Undefined
                 pass
+        elif CritType == FT_BelongToMeshGroup:
+            # Check that Threshold is a group
+            if isinstance(aThreshold, SMESH._objref_SMESH_GroupBase):
+                if aThreshold.GetType() != elementType:
+                    raise ValueError, "Group type mismatches Element type"
+                aCriterion.ThresholdStr = aThreshold.GetName()
+                aCriterion.ThresholdID  = salome.orb.object_to_string( aThreshold )
+            else:
+                raise TypeError, "The Threshold should be a Mesh Group"
         elif CritType == FT_RangeOfIds:
-            # Checks that Threshold is string
+            # Check that Threshold is string
             if isinstance(aThreshold, str):
                 aCriterion.ThresholdStr = aThreshold
             else:
-                print "Error: The Threshold should be a string."
-                return None
+                raise TypeError, "The Threshold should be a string."
         elif CritType == FT_CoplanarFaces:
-            # Checks the Threshold
+            # Check the Threshold
             if isinstance(aThreshold, int):
                 aCriterion.ThresholdID = str(aThreshold)
             elif isinstance(aThreshold, str):
@@ -768,10 +775,10 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                     raise ValueError, "Invalid ID of mesh face: '%s'"%aThreshold
                 aCriterion.ThresholdID = aThreshold
             else:
-                raise ValueError,\
+                raise TypeError,\
                       "The Threshold should be an ID of mesh face and not '%s'"%aThreshold
         elif CritType == FT_ConnectedElements:
-            # Checks the Threshold
+            # Check the Threshold
             if isinstance(aThreshold, geomBuilder.GEOM._objref_GEOM_Object): # shape
                 aCriterion.ThresholdID = aThreshold.GetStudyEntry()
                 if not aCriterion.ThresholdID:
@@ -791,11 +798,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 else:
                     aCriterion.ThresholdStr = aThreshold # hope that it's point coordinates
             else:
-                raise ValueError,\
+                raise TypeError,\
                       "The Threshold should either a VERTEX, or a node ID, "\
                       "or a list of point coordinates and not '%s'"%aThreshold
         elif CritType == FT_ElemGeomType:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.Threshold = self.EnumToLong(aThreshold)
                 assert( aThreshold in SMESH.GeometryType._items )
@@ -803,12 +810,11 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 if isinstance(aThreshold, int):
                     aCriterion.Threshold = aThreshold
                 else:
-                    print "Error: The Threshold should be an integer or SMESH.GeometryType."
-                    return None
+                    raise TypeError, "The Threshold should be an integer or SMESH.GeometryType."
                 pass
             pass
         elif CritType == FT_EntityType:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.Threshold = self.EnumToLong(aThreshold)
                 assert( aThreshold in SMESH.EntityType._items )
@@ -816,18 +822,16 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 if isinstance(aThreshold, int):
                     aCriterion.Threshold = aThreshold
                 else:
-                    print "Error: The Threshold should be an integer or SMESH.EntityType."
-                    return None
+                    raise TypeError, "The Threshold should be an integer or SMESH.EntityType."
                 pass
             pass
         
         elif CritType == FT_GroupColor:
-            # Checks the Threshold
+            # Check the Threshold
             try:
                 aCriterion.ThresholdStr = self.ColorToString(aThreshold)
             except:
-                print "Error: The threshold value should be of SALOMEDS.Color type"
-                return None
+                raise TypeError, "The threshold value should be of SALOMEDS.Color type"
             pass
         elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_FreeNodes, FT_FreeFaces,
                           FT_LinearOrQuadratic, FT_BadOrientedVolume,
@@ -845,7 +849,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
                 aThreshold = float(aThreshold)
                 aCriterion.Threshold = aThreshold
             except:
-                print "Error: The Threshold should be a number."
+                raise TypeError, "The Threshold should be a number."
                 return None
 
         if Threshold ==  FT_LogicalNOT or UnaryOp ==  FT_LogicalNOT: