Salome HOME
IPAL52827: Very few filtering criteria available in filter dialog called from Remove...
authoreap <eap@opencascade.com>
Thu, 16 Jul 2015 17:52:26 +0000 (20:52 +0300)
committereap <eap@opencascade.com>
Thu, 16 Jul 2015 17:52:26 +0000 (20:52 +0300)
IPAL52831: Veeery long awaiting for Mesh Information dialog appearance
IPAL52822: Find Elements By Point does not find coincident nodes
IPAL52821: Find Elements By Point dialog: no types available for search if there are only nodes in the mesh
IPAL52823: mesh.GetSubMeshElementsId( subShape ) works wrong if subShape is retrieved indirectly

16 files changed:
doc/salome/examples/transforming_meshes_ex09.py
doc/salome/examples/transforming_meshes_ex10.py
doc/salome/gui/SMESH/input/sewing_meshes.doc
src/SMESHGUI/SMESHGUI_FilterDlg.cxx
src/SMESHGUI/SMESHGUI_Hypotheses.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.cxx
src/SMESHGUI/SMESHGUI_MeshInfo.h
src/SMESHGUI/SMESHGUI_RemoveElementsDlg.cxx
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESHUtils/SMESH_MeshAlgos.hxx
src/SMESHUtils/SMESH_OctreeNode.cxx
src/SMESHUtils/SMESH_OctreeNode.hxx
src/SMESH_I/SMESH_Filter_i.hxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG/smesh_algorithm.py

index 62fea88..9264a5c 100644 (file)
@@ -11,35 +11,40 @@ import SMESH, SALOMEDS
 from salome.smesh import smeshBuilder
 smesh =  smeshBuilder.New(salome.myStudy)
 
-# create two faces of the box
-box1 = geompy.MakeBox(0., 0., 0., 20., 20., 15.)
-facesList1 = geompy.SubShapeAll(box1, geompy.ShapeType["FACE"])
-face1 = facesList1[2]
-
-box2 = geompy.MakeBox(0., 5., 0., 20., 20., 15.)
-facesList2 = geompy.SubShapeAll(box2, geompy.ShapeType["FACE"])
-face2 = facesList2[1]
-
-edgesList = geompy.SubShapeAll(face2, geompy.ShapeType["EDGE"])
-edge1 = edgesList[2]
-
-aComp = geompy.MakeCompound([face1, face2])
-geompy.addToStudy(aComp, "Two faces")
+# make two not sewed quadranges
+OY0 = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OY1 = geompy.MakeTranslation( OY0, 1, 0, 0, theName="OY1" )
+OY2 = geompy.MakeTranslation( OY0, 1.01, 0, 0, theName="OY2" )
+OY3 = geompy.MakeTranslation( OY0, 2, 0, 0 )
+q1  = geompy.MakeQuad2Edges( OY0, OY1 )
+q2  = geompy.MakeQuad2Edges( OY2, OY3 )
+
+shape = geompy.MakeCompound( [q1,q2], theName='shape' )
+
+# make a non-uniform quadrangle mesh on two faces
+mesh = smesh.Mesh(shape, "Two faces : quadrangle mesh")
+mesh.Segment().Arithmetic1D( 0.1, 0.4 )
+mesh.Segment(q1).NumberOfSegments( 5 )
+mesh.Quadrangle()
+mesh.Compute()
 
-# create a mesh on two faces
-mesh = smesh.Mesh(aComp, "Two faces : quadrangle mesh")
+# sew free borders
 
-algo1D = mesh.Segment()
-algo1D.NumberOfSegments(4)
-algo2D = mesh.Quadrangle()
+segs1 = mesh.GetSubMeshElementsId( OY1 ) # mesh segments generated on borders
+segs2 = mesh.GetSubMeshElementsId( OY2 )
 
-algo_local = mesh.Segment(edge1)
-algo_local.Arithmetic1D(1, 4)
-algo_local.Propagation()
+FirstNodeID1  = mesh.GetElemNode( segs1[0], 0 )
+SecondNodeID1 = mesh.GetElemNode( segs1[0], 1 )
+LastNodeID1   = mesh.GetElemNode( segs1[-1], 1 )
+FirstNodeID2  = mesh.GetElemNode( segs2[0], 0 )
+SecondNodeID2 = mesh.GetElemNode( segs2[0], 1 )
+LastNodeID2   = mesh.GetElemNode( segs2[-1], 1 )
+CreatePolygons = True
+CreatePolyedrs = False
 
-mesh.Compute()
+res = mesh.SewFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
+                          FirstNodeID2, SecondNodeID2, LastNodeID2,
+                          CreatePolygons, CreatePolyedrs )
+print res
+print "nb polygons:", mesh.NbPolygons()
 
-# sew free borders
-# FirstNodeID1, SecondNodeID1, LastNodeID1,
-# FirstNodeID2, SecondNodeID2, LastNodeID2, CreatePolygons, CreatePolyedrs
-mesh.SewFreeBorders(6, 21, 5, 1, 12, 3, 0, 0)
index 426a011..e0120b4 100644 (file)
@@ -20,7 +20,7 @@ aComp = geompy.MakeCompound([box1, box2])
 geompy.addToStudy(aComp, "Two boxes")
 
 # create a mesh on two boxes
-mesh = smesh.Mesh(aComp, "Two faces : quadrangle mesh")
+mesh = smesh.Mesh(aComp, "Sew Side Elements")
 
 algo1D = mesh.Segment()
 algo1D.NumberOfSegments(2)
@@ -33,6 +33,31 @@ algo_local.Propagation()
 mesh.Compute()
 
 # sew side elements
-# IDsOfSide1Elements, IDsOfSide2Elements,
-# NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge, NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge
-mesh.SewSideElements([69, 70, 71, 72], [91, 92, 89, 90], 8, 38, 23, 58)
+
+# find elements to sew
+face1 = geompy.GetFaceNearPoint( aComp, geompy.MakeVertex( 5, 10, 5 ))
+IDsOfSide1Elements = mesh.GetSubMeshElementsId( face1 )
+print "side faces 1:",IDsOfSide1Elements
+
+face1Translated = geompy.MakeTranslation( face1, 0,5,0 )
+faceFilter = smesh.GetFilter( SMESH.FACE, SMESH.FT_BelongToGeom,'=', face1Translated )
+IDsOfSide2Elements = mesh.GetIdsFromFilter( faceFilter )
+print "side faces 2:",IDsOfSide2Elements
+
+# find corresponding nodes on sides
+edge1 = geompy.GetEdgeNearPoint( aComp, geompy.MakeVertex( 0, 10, 5 ))
+segs1 = mesh.GetSubMeshElementsId( edge1 ) # mesh segments generated on edge1
+NodeID1OfSide1ToMerge = mesh.GetElemNode( segs1[0], 0 )
+NodeID2OfSide1ToMerge = mesh.GetElemNode( segs1[0], 1 )
+print "nodes of side1:", [NodeID1OfSide1ToMerge,NodeID2OfSide1ToMerge]
+
+edge2 = geompy.GetEdgeNearPoint( aComp, geompy.MakeVertex( 0, 15, 5 ))
+segs2 = mesh.GetSubMeshElementsId( edge2 ) # mesh segments generated on edge2
+NodeID1OfSide2ToMerge = mesh.GetElemNode( segs2[0], 0 )
+NodeID2OfSide2ToMerge = mesh.GetElemNode( segs2[0], 1 )
+print "nodes of side2:", [NodeID1OfSide2ToMerge,NodeID2OfSide2ToMerge]
+
+res = mesh.SewSideElements(IDsOfSide1Elements, IDsOfSide2Elements,
+                           NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
+                           NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
+print res
index 88edc1e..ad5f15e 100644 (file)
@@ -50,6 +50,12 @@ corresponding end nodes of two borders will be merged. Intermediate
 nodes of two borders will be either merged or inserted into faces of
 the opposite border.
 
+In practice the borders to sew often coincide and in this case it is
+difficult to specify the first and the last nodes of a border since
+they coincide with the first and the last nodes of the other
+border. To cope with this, manually \ref merging_nodes_page to fuse
+each pair of coincident nodes into one.
+
 The sewing algorithm is as follows:
 <ol>
 <li>The parameter (U) of each node within a border is computed. So
index afbfd68..3a3e8e8 100755 (executable)
@@ -2891,6 +2891,11 @@ void SMESHGUI_FilterDlg::Init (const int type, const bool setInViewer)
 //=======================================================================
 void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes, const bool setInViewer)
 {
+  if ( theTypes.empty() )
+  {
+    Init( SMESH::ALL, setInViewer );
+    return;
+  }
   mySourceWg  = 0;
   myTypes     = theTypes;
   myMesh      = SMESH::SMESH_Mesh::_nil();
index 36b29d8..06d9172 100644 (file)
@@ -665,6 +665,7 @@ void SMESHGUI_HypothesisDlg::setCustomFrame( QFrame* f )
 
 void SMESHGUI_HypothesisDlg::accept()
 {
+  SUIT_OverrideCursor wc; // some creators temporary set params to a hyp which can be long
   QString msg;
   if ( myCreator && !myCreator->checkParams( msg ) )
   {
index f997d9a..3e8c18e 100644 (file)
@@ -2258,8 +2258,11 @@ void SMESHGUI_TreeElemInfo::saveInfo( QTextStream &out )
 /*!
   \brief Contructor
 */
-GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetItem* item, QObject* parent )
-  : QObject( parent ), myItem( item )
+GrpComputor::GrpComputor( SMESH::SMESH_GroupBase_ptr grp,
+                          QTreeWidgetItem*           item,
+                          QObject*                   parent,
+                          bool                       toComputeSize)
+  : QObject( parent ), myItem( item ), myToComputeSize( toComputeSize )
 {
   myGroup = SMESH::SMESH_GroupBase::_narrow( grp );
 }
@@ -2272,9 +2275,9 @@ void GrpComputor::compute()
   if ( !CORBA::is_nil( myGroup ) && myItem ) {
     QTreeWidgetItem* item = myItem;
     myItem = 0;
-    int nbNodes = myGroup->GetNumberOfNodes();
+    int nb = myToComputeSize ? myGroup->Size() : myGroup->GetNumberOfNodes();
     item->treeWidget()->removeItemWidget( item, 1 );
-    item->setText( 1, QString::number( nbNodes ));
+    item->setText( 1, QString::number( nb ));
   }
 }
 
@@ -2506,10 +2509,28 @@ void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetIte
     etypeItem->setText( 1, etype );
   }
 
-  // size
+  SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
+  bool            meshLoaded = mesh->IsLoaded();
+
+  // size. Don't call grp->Size() for GroupOnFilter - issue IPAL52831
+  int groupSize = -1;
+  if ( grp->IsNodeInfoAvailable() || CORBA::is_nil( aFltGroup ))
+    groupSize = grp->Size();
+
   QTreeWidgetItem* sizeItem = createItem( parent, Bold );
   sizeItem->setText( 0, tr( "SIZE" ) );
-  sizeItem->setText( 1, QString::number( grp->Size() ) );
+  if ( groupSize > -1 ) {
+    sizeItem->setText( 1, QString::number( groupSize ) );
+  }
+  else {
+    QPushButton* btn = new QPushButton( tr( meshLoaded ? "COMPUTE" : "LOAD"), this );
+    setItemWidget( sizeItem, 1, btn );
+    GrpComputor* comp = new GrpComputor( grp, sizeItem, this, /*size=*/true );
+    connect( btn, SIGNAL( clicked() ), comp, SLOT( compute() ) );
+    myComputors.append( comp );
+    if ( !meshLoaded )
+      connect( btn, SIGNAL( clicked() ), this, SLOT( changeLoadToCompute() ) );
+  }
 
   // color
   SALOMEDS::Color color = grp->GetColor();
@@ -2522,9 +2543,7 @@ void SMESHGUI_AddInfo::groupInfo( SMESH::SMESH_GroupBase_ptr grp, QTreeWidgetIte
     QTreeWidgetItem* nodesItem = createItem( parent, Bold );
     nodesItem->setText( 0, tr( "NB_NODES" ) );
     int nbNodesLimit = SMESHGUI::resourceMgr()->integerValue( "SMESH", "info_groups_nodes_limit", 100000 );
-    SMESH::SMESH_Mesh_var mesh = grp->GetMesh();
-    bool meshLoaded = mesh->IsLoaded();
-    bool toShowNodes = ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || grp->Size() <= nbNodesLimit );
+    bool toShowNodes = groupSize >= 0 ? ( grp->IsNodeInfoAvailable() || nbNodesLimit <= 0 || groupSize <= nbNodesLimit ) : false;
     if ( toShowNodes && meshLoaded ) {
       // already calculated and up-to-date
       nodesItem->setText( 1, QString::number( grp->GetNumberOfNodes() ) );
index 357f269..f06db38 100644 (file)
@@ -250,7 +250,7 @@ class GrpComputor: public QObject
   Q_OBJECT;
 
 public:
-  GrpComputor( SMESH::SMESH_GroupBase_ptr, QTreeWidgetItem*, QObject* );
+  GrpComputor( SMESH::SMESH_GroupBase_ptr, QTreeWidgetItem*, QObject*, bool = false);
   QTreeWidgetItem* getItem() { return myItem; }
 
 public slots:
@@ -259,6 +259,7 @@ public slots:
 private:
   SMESH::SMESH_GroupBase_var myGroup;
   QTreeWidgetItem*           myItem;
+  bool                       myToComputeSize;
 };
 
 class SMESHGUI_EXPORT SMESHGUI_AddInfo : public QTreeWidget
index 577f601..4ad814a 100644 (file)
@@ -517,11 +517,17 @@ void SMESHGUI_RemoveElementsDlg::setFilters()
     SUIT_MessageBox::critical(this,
                               tr("SMESH_ERROR"),
                               tr("NO_MESH_SELECTED"));
-   return;
+    return;
   }
   if ( !myFilterDlg )
     myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::ALL );
 
+  QList<int> types;
+  if ( myMesh->NbEdges()   ) types << SMESH::EDGE;
+  if ( myMesh->NbFaces()   ) types << SMESH::FACE;
+  if ( myMesh->NbVolumes() ) types << SMESH::VOLUME;
+
+  myFilterDlg->Init( types );
   myFilterDlg->SetSelection();
   myFilterDlg->SetMesh( myMesh );
   myFilterDlg->SetSourceWg( LineEditC1A1 );
index 9f08445..f3face9 100644 (file)
@@ -170,6 +170,18 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
 
   //---------------------------------------------------------------------
   /*!
+   * \brief Finds nodes located within a tolerance near a point 
+   */
+  int FindNearPoint(const gp_Pnt&                        point,
+                    const double                         tolerance,
+                    std::vector< const SMDS_MeshNode* >& foundNodes)
+  {
+    myOctreeNode->NodesAround( point.Coord(), foundNodes, tolerance );
+    return foundNodes.size();
+  }
+
+  //---------------------------------------------------------------------
+  /*!
    * \brief Destructor
    */
   ~SMESH_NodeSearcherImpl() { delete myOctreeNode; }
@@ -696,21 +708,21 @@ FindElementsByPoint(const gp_Pnt&                      point,
     if ( !_nodeSearcher )
       _nodeSearcher = new SMESH_NodeSearcherImpl( _mesh );
 
-    const SMDS_MeshNode* closeNode = _nodeSearcher->FindClosestTo( point );
-    if ( !closeNode ) return foundElements.size();
-
-    if ( point.Distance( SMESH_TNodeXYZ( closeNode )) > tolerance )
-      return foundElements.size(); // to far from any node
+    std::vector< const SMDS_MeshNode* > foundNodes;
+    _nodeSearcher->FindNearPoint( point, tolerance, foundNodes );
 
     if ( type == SMDSAbs_Node )
     {
-      foundElements.push_back( closeNode );
+      foundElements.assign( foundNodes.begin(), foundNodes.end() );
     }
     else
     {
-      SMDS_ElemIteratorPtr elemIt = closeNode->GetInverseElementIterator( type );
-      while ( elemIt->more() )
-        foundElements.push_back( elemIt->next() );
+      for ( size_t i = 0; i < foundNodes.size(); ++i )
+      {
+        SMDS_ElemIteratorPtr elemIt = foundNodes[i]->GetInverseElementIterator( type );
+        while ( elemIt->more() )
+          foundElements.push_back( elemIt->next() );
+      }
     }
   }
   // =================================================================================
index 487f8d2..fe5074e 100644 (file)
@@ -55,6 +55,9 @@ struct SMESHUtils_EXPORT SMESH_NodeSearcher
 {
   virtual const SMDS_MeshNode* FindClosestTo( const gp_Pnt& pnt ) = 0;
   virtual void MoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt ) = 0;
+  virtual int  FindNearPoint(const gp_Pnt&                        point,
+                             const double                         tolerance,
+                             std::vector< const SMDS_MeshNode* >& foundNodes) = 0;
 };
 
 //=======================================================================
index 772a50f..e55128e 100644 (file)
@@ -189,6 +189,7 @@ void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
 //================================================================================
 /*!
  * \brief Return in dist2Nodes nodes mapped to their square distance from Node
+ *        Tries to find a closest node.
  *  \param node - node to find nodes closest to
  *  \param dist2Nodes - map of found nodes and their distances
  *  \param precision - radius of a sphere to check nodes inside
@@ -241,6 +242,44 @@ bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
   return false;
 }
 
+//================================================================================
+/*!
+ * \brief Return a list of nodes close to a point
+ *  \param [in] point - point
+ *  \param [out] nodes - found nodes
+ *  \param [in] precision - allowed distance from \a point
+ */
+//================================================================================
+
+void SMESH_OctreeNode::NodesAround(const gp_XYZ&                      point,
+                                   std::vector<const SMDS_MeshNode*>& nodes,
+                                   double                             precision)
+{
+  if ( isInside( point, precision ))
+  {
+    if ( isLeaf() && NbNodes() )
+    {
+      double minDist2 = precision * precision;
+      TIDSortedNodeSet::iterator nIt = myNodes.begin();
+      for ( ; nIt != myNodes.end(); ++nIt )
+      {
+        SMESH_TNodeXYZ p2( *nIt );
+        double dist2 = ( point - p2 ).SquareModulus();
+        if ( dist2 <= minDist2 )
+          nodes.push_back( p2._node );
+      }
+    }
+    else if ( myChildren )
+    {
+      for (int i = 0; i < 8; i++)
+      {
+        SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
+        myChild->NodesAround( point, nodes, precision);
+      }
+    }
+  }
+}
+
 //=============================
 /*!
  * \brief  Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
index 51242bb..2cd22a3 100644 (file)
 #ifndef _SMESH_OCTREENODE_HXX_
 #define _SMESH_OCTREENODE_HXX_
 
-#include "SMESH_Utils.hxx"
+#include "SMDS_ElemIterator.hxx"
+#include "SMDS_MeshNode.hxx"
 #include "SMESH_Octree.hxx"
+#include "SMESH_Utils.hxx"
+
 #include <gp_Pnt.hxx>
-#include "SMDS_MeshNode.hxx"
 
 #include <list>
 #include <set>
 #include <map>
-
-#include "SMDS_ElemIterator.hxx"
+#include <vector>
 
 //forward declaration
 class SMDS_MeshNode;
@@ -49,34 +50,35 @@ typedef SMDS_Iterator<SMESH_OctreeNode*>              SMESH_OctreeNodeIterator;
 typedef boost::shared_ptr<SMESH_OctreeNodeIterator>   SMESH_OctreeNodeIteratorPtr;
 typedef std::set< const SMDS_MeshNode*, TIDCompare >  TIDSortedNodeSet;
 
-class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree {
-
-public:
+class SMESHUtils_EXPORT SMESH_OctreeNode : public SMESH_Octree
+{
+ public:
 
   // Constructor
   SMESH_OctreeNode (const TIDSortedNodeSet& theNodes, const int maxLevel = 8,
                     const int maxNbNodes = 5, const double minBoxSize = 0.);
 
-//=============================
-/*!
- * \brief Empty destructor
- */
-//=============================
+  // destructor
   virtual ~SMESH_OctreeNode () {};
 
   // Tells us if Node is inside the current box with the precision "precision"
   virtual const bool isInside(const gp_XYZ& p, const double precision = 0.);
 
   // Return in Result a list of Nodes potentials to be near Node
-  void               NodesAround(const SMDS_MeshNode *            Node,
-                                 std::list<const SMDS_MeshNode*>* Result,
+  void               NodesAround(const SMDS_MeshNode *            node,
+                                 std::list<const SMDS_MeshNode*>* result,
                                  const double                     precision = 0.);
 
   // Return in dist2Nodes nodes mapped to their square distance from Node
-  bool               NodesAround(const gp_XYZ& node,
+  bool               NodesAround(const gp_XYZ&                           point,
                                  std::map<double, const SMDS_MeshNode*>& dist2Nodes,
                                  double                                  precision);
 
+  // Return a list of Nodes close to a point
+  void               NodesAround(const gp_XYZ&                      point,
+                                 std::vector<const SMDS_MeshNode*>& nodes,
+                                 double                             precision);
+
   // Return in theGroupsOfNodes a list of group of nodes close to each other within theTolerance
   // Search for all the nodes in nodes
   void               FindCoincidentNodes ( TIDSortedNodeSet*           nodes,
index 92b1235..a629f67 100644 (file)
@@ -1013,8 +1013,8 @@ namespace SMESH
 
     std::vector< SMESH_GroupBase_i* > myBaseGroups;
   };
-  
-  
+
+
   /*
     FILTER LIBRARY
   */
index fed66cd..b521af9 100644 (file)
@@ -5141,6 +5141,8 @@ SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
+  if (_impl->NbNodes() &&
+      nbTypes == 0 )         types[nbTypes++] = SMESH::NODE;
   types->length( nbTypes );
 
   return types._retn();
index 78495e6..dfb2248 100644 (file)
@@ -2505,8 +2505,8 @@ class Mesh:
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetSubMeshElementsId(self, Shape):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementsId(ShapeID)
@@ -2518,7 +2518,7 @@ class Mesh:
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetSubMeshNodesId(self, Shape, all):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
             ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
@@ -2530,8 +2530,8 @@ class Mesh:
     #  @return element type
     #  @ingroup l1_meshinfo
     def GetSubMeshElementType(self, Shape):
-        if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+        if isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object):
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementType(ShapeID)
@@ -2920,7 +2920,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnVertex(self, NodeID, Vertex):
         if ( isinstance( Vertex, geomBuilder.GEOM._objref_GEOM_Object)):
-            VertexID = Vertex.GetSubShapeIndices()[0]
+            VertexID = self.geompyD.GetSubShapeID( self.geom, Vertex )
         else:
             VertexID = Vertex
         try:
@@ -2938,7 +2938,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnEdge(self, NodeID, Edge, paramOnEdge):
         if ( isinstance( Edge, geomBuilder.GEOM._objref_GEOM_Object)):
-            EdgeID = Edge.GetSubShapeIndices()[0]
+            EdgeID = self.geompyD.GetSubShapeID( self.geom, Edge )
         else:
             EdgeID = Edge
         try:
@@ -2956,7 +2956,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeOnFace(self, NodeID, Face, u, v):
         if ( isinstance( Face, geomBuilder.GEOM._objref_GEOM_Object)):
-            FaceID = Face.GetSubShapeIndices()[0]
+            FaceID = self.geompyD.GetSubShapeID( self.geom, Face )
         else:
             FaceID = Face
         try:
@@ -2972,7 +2972,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetNodeInVolume(self, NodeID, Solid):
         if ( isinstance( Solid, geomBuilder.GEOM._objref_GEOM_Object)):
-            SolidID = Solid.GetSubShapeIndices()[0]
+            SolidID = self.geompyD.GetSubShapeID( self.geom, Solid )
         else:
             SolidID = Solid
         try:
@@ -2988,7 +2988,7 @@ class Mesh:
     #  @ingroup l2_modif_add
     def SetMeshElementOnShape(self, ElementID, Shape):
         if ( isinstance( Shape, geomBuilder.GEOM._objref_GEOM_Object)):
-            ShapeID = Shape.GetSubShapeIndices()[0]
+            ShapeID = self.geompyD.GetSubShapeID( self.geom, Shape )
         else:
             ShapeID = Shape
         try:
@@ -4589,7 +4589,7 @@ class Mesh:
     def ClearLastCreated(self):
         self.editor.ClearLastCreated()
 
-    ## Creates Duplicates given elements, i.e. creates new elements based on the 
+    ## Creates duplicates of given elements, i.e. creates new elements based on the 
     #  same nodes as the given ones.
     #  @param theElements - container of elements to duplicate. It can be a Mesh,
     #         sub-mesh, group, filter or a list of element IDs. If \a theElements is
index ff601b4..df02724 100644 (file)
@@ -288,12 +288,7 @@ class Mesh_Algorithm:
             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
         if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
             import GEOM
-            faceIDs = []
-            for f in faces:
-                if self.mesh.geompyD.ShapeIdToType( f.GetType() ) == "GROUP":
-                    faceIDs += f.GetSubShapeIndices()
-                else:
-                    faceIDs += [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f)]
+            faceIDs = [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces]
             faces = faceIDs
         hyp = self.Hypothesis("ViscousLayers",
                               [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],