]> SALOME platform Git repositories - modules/smesh.git/commitdiff
Salome HOME
Implement MakePolyLine()
authoreap <eap@opencascade.com>
Wed, 30 Aug 2017 16:38:26 +0000 (19:38 +0300)
committereap <eap@opencascade.com>
Wed, 30 Aug 2017 16:38:26 +0000 (19:38 +0300)
for ASERIS module

Modified sources = master(223c5b7) + new development.

14 files changed:
idl/SMESH_MeshEditor.idl
src/SMDS/ObjectPool.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHGUI/SMESHGUI_MergeDlg.cxx
src/SMESHGUI/SMESHGUI_MergeDlg.h
src/SMESHUtils/SMESH_MeshAlgos.cxx
src/SMESHUtils/SMESH_MeshAlgos.hxx
src/SMESHUtils/SMESH_TryCatch.cxx
src/SMESHUtils/SMESH_TryCatch.hxx
src/SMESHUtils/SMESH_TypeDefs.hxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py

index 7cbe67bfff19fb3b076c7cb1f0129664fc0866f1..199f1bbc109f2dafd304327adae08d40ac90b5c5 100644 (file)
@@ -57,6 +57,24 @@ module SMESH
   };
 
 
+  // structure used in MakePolyLine() to define a cutting plane
+  struct PolySegment
+  {
+    // point 1: if node1ID2 > 0, then the point is in the middle of a face edge defined
+    //          by two nodes, else it is at node1ID1
+    long node1ID1;
+    long node1ID2;
+
+    // point 2: if node2ID2 > 0, then the point is in the middle of a face edge defined
+    //          by two nodes, else it is at node2ID1
+    long node2ID1;
+    long node2ID2;
+
+    DirStruct vector; // vector on the plane; to use a default plane set vector = (0,0,0)
+  };
+  typedef sequence<PolySegment> ListOfPolySegments;
+
+
   /*!
    * This interface makes modifications on the Mesh - removing elements and nodes etc.
    */
@@ -93,7 +111,7 @@ module SMESH
     void ClearLastCreated() raises (SALOME::SALOME_Exception);
 
     /*!
-     * \brief Returns description of an error/warning occured during the last operation
+     * \brief Returns description of an error/warning occurred during the last operation
      */
     ComputeError GetLastError() raises (SALOME::SALOME_Exception);
 
@@ -689,7 +707,8 @@ module SMESH
       raises (SALOME::SALOME_Exception);
 
     void MergeNodes (in array_of_long_array    GroupsOfNodes,
-                     in SMESH::ListOfIDSources NodesToKeep)
+                     in SMESH::ListOfIDSources NodesToKeep,
+                     in boolean                AvoidMakingHoles)
       raises (SALOME::SALOME_Exception);
 
     /*!
@@ -1183,7 +1202,28 @@ module SMESH
                         in GEOM::GEOM_Object theShape,
                         in string groupName,
                         in double_array theNodesCoords,
-                        out array_of_long_array GroupsOfNodes) 
+                        out array_of_long_array GroupsOfNodes)
+      raises (SALOME::SALOME_Exception);
+
+
+    /*!
+     * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+     *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+     *        plane passing through pairs of points specified by each PolySegment structure.
+     *        If there are several paths connecting a pair of points, the shortest path is
+     *        selected by the module. Position of the cutting plane is defined by the two
+     *        points and an optional vector lying on the plane specified by a PolySegment.
+     *        By default the vector is defined by Mesh module as following. A middle point
+     *        of the two given points is computed. The middle point is projected to the mesh.
+     *        The vector goes from the middle point to the projection point. In case of planar
+     *        mesh, the vector is normal to the mesh.
+     *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+     *        Return the used vector which goes from the middle point to its projection.
+     *  \param [in] groupName - optional name of a group where created mesh segments will
+     *        be added.
+     */
+    void MakePolyLine(inout ListOfPolySegments segments,
+                      in    string             groupName)
       raises (SALOME::SALOME_Exception);
   };
 };
index 5e5f0d289d275eff3d2c3d10a6b99d80b88d400d..ef514b353b0388fdcf4b61eb0cb8924a1742327e 100644 (file)
 #define _OBJECTPOOL_HXX_
 
 #include <vector>
-//#include <stack>
 #include <iostream>
 
+#include "SMDS_Iterator.hxx"
+
 namespace
 {
   // assure deallocation of memory of a vector
@@ -33,18 +34,22 @@ namespace
   }
 }
 
+template<class X> class ObjectPoolIterator;
+
 template<class X> class ObjectPool
 {
 
 private:
-  std::vector<X*> _chunkList;
+  std::vector<X*>   _chunkList;
   std::vector<bool> _freeList;
-  int _nextFree;
-  int _maxAvail;
-  int _chunkSize;
-  int _maxOccupied;
-  int _nbHoles;
-  int _lastDelChunk;
+  int               _nextFree;    // either the 1st hole or last added
+  int               _maxAvail;    // nb allocated elements
+  int               _chunkSize;
+  int               _maxOccupied; // max used ID
+  int               _nbHoles;
+  int               _lastDelChunk;
+
+  friend class ObjectPoolIterator<X>;
 
   int getNextFree()
   {
@@ -76,16 +81,16 @@ private:
   }
 
 public:
-  ObjectPool(int nblk)
+  ObjectPool(int nblk = 1024)
   {
-    _chunkSize = nblk;
-    _nextFree = 0;
-    _maxAvail = 0;
-    _maxOccupied = 0;
-    _nbHoles = 0;
+    _chunkSize    = nblk;
+    _nextFree     = 0;
+    _maxAvail     = 0;
+    _maxOccupied  = -1;
+    _nbHoles      = 0;
+    _lastDelChunk = 0;
     _chunkList.clear();
     _freeList.clear();
-    _lastDelChunk = 0;
   }
 
   virtual ~ObjectPool()
@@ -105,16 +110,16 @@ public:
         _freeList.insert(_freeList.end(), _chunkSize, true);
         _maxAvail += _chunkSize;
         _freeList[_nextFree] = false;
-        obj = newChunk; // &newChunk[0];
+        obj = newChunk;
       }
     else
       {
         int chunkId = _nextFree / _chunkSize;
         int rank = _nextFree - chunkId * _chunkSize;
         _freeList[_nextFree] = false;
-        obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
+        obj = _chunkList[chunkId] + rank;
       }
-    if (_nextFree < _maxOccupied)
+    if (_nextFree <= _maxOccupied)
       {
         _nbHoles-=1;
       }
@@ -122,7 +127,6 @@ public:
       {
         _maxOccupied = _nextFree;
       }
-    //obj->init();
     return obj;
   }
 
@@ -148,10 +152,10 @@ public:
     if (toFree < _nextFree)
       _nextFree = toFree;
     if (toFree < _maxOccupied)
-      _nbHoles += 1;
+      ++_nbHoles;
+    else
+      --_maxOccupied;
     _lastDelChunk = i;
-    //obj->clean();
-    //checkDelete(i); compactage non fait
   }
 
   void clear()
@@ -167,6 +171,37 @@ public:
     clearVector( _freeList );
   }
 
+  // nb allocated elements
+  size_t size() const
+  {
+    return _freeList.size();
+  }
+
+  // nb used elements
+  size_t nbElements() const
+  {
+    return _maxOccupied + 1 - _nbHoles;
+  }
+
+  // return an element w/o any check
+  const X* operator[]( size_t i ) const // i < size()
+  {
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
+  // return only being used element
+  const X* at( size_t i ) const // i < size()
+  {
+    if ( i >= size() || _freeList[ i ] )
+      return 0;
+
+    int chunkId = i / _chunkSize;
+    int    rank = i - chunkId * _chunkSize;
+    return _chunkList[ chunkId ] + rank;
+  }
+
   //  void destroy(int toFree)
   //  {
   //    // no control 0<= toFree < _freeList.size()
@@ -177,4 +212,41 @@ public:
 
 };
 
+template<class X> class ObjectPoolIterator : public SMDS_Iterator<const X*>
+{
+  const ObjectPool<X>& _pool;
+  int                  _i, _nbFound;
+public:
+
+  ObjectPoolIterator( const ObjectPool<X>& pool ) : _pool( pool ), _i( 0 ), _nbFound( 0 )
+  {
+    if ( more() && _pool._freeList[ _i ] == true )
+    {
+      next();
+      --_nbFound;
+    }
+  }
+
+  virtual bool more()
+  {
+    return ( _i <= _pool._maxOccupied && _nbFound < (int)_pool.nbElements() );
+  }
+
+  virtual const X* next()
+  {
+    const X* x = 0;
+    if ( more() )
+    {
+      x = _pool[ _i ];
+
+      ++_nbFound;
+
+      for ( ++_i; _i <= _pool._maxOccupied; ++_i )
+        if ( _pool._freeList[ _i ] == false )
+          break;
+    }
+    return x;
+  }
+};
+
 #endif
index 056da7050d0089695521d1503a50de99e9016ea0..7b7c1a40e290cce76224da5c6deedb995817c5e7 100644 (file)
@@ -98,6 +98,9 @@
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx>
+#include <OSD_Parallel.hxx>
+
+#include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
 
@@ -1168,7 +1171,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
  * \brief Reorient faces.
  * \param theFaces - the faces to reorient. If empty the whole mesh is meant
  * \param theDirection - desired direction of normal of \a theFace
- * \param theFace - one of \a theFaces that sould be oriented according to
+ * \param theFace - one of \a theFaces that should be oriented according to
  *        \a theDirection and whose orientation defines orientation of other faces
  * \return number of reoriented faces.
  */
@@ -2398,7 +2401,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
         }
         else
         {
-          // among possible triangles create ones discribed by split method
+          // among possible triangles create ones described by split method
           const int* nInd = volTool.GetFaceNodesIndices( iF );
           int nbVariants = ( nbNodes == 4 ? 2 : nbNodes );
           int iCom = 0; // common node of triangle faces to split into
@@ -2524,7 +2527,7 @@ void SMESH_MeshEditor::GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
 
   // Fill theFacets starting from facetID of startHex
 
-  // facets used for seach of volumes adjacent to already treated ones
+  // facets used for searching of volumes adjacent to already treated ones
   typedef pair< TFacetOfElem::iterator, int > TElemFacets;
   typedef map< TVolumeFaceKey, TElemFacets  > TFacetMap;
   TFacetMap facetsToCheck;
@@ -4342,18 +4345,18 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         }
       }
       if ( maxRatio <= theTgtAspectRatio ) {
-        MESSAGE("-- quality achived --");
+        //MESSAGE("-- quality achieved --");
         break;
       }
       if (it+1 == theNbIterations) {
-        MESSAGE("-- Iteration limit exceeded --");
+        //MESSAGE("-- Iteration limit exceeded --");
       }
     } // smoothing iterations
 
-    MESSAGE(" Face id: " << *fId <<
-            " Nb iterstions: " << it <<
-            " Displacement: " << maxDisplacement <<
-            " Aspect Ratio " << maxRatio);
+    // MESSAGE(" Face id: " << *fId <<
+    //         " Nb iterstions: " << it <<
+    //         " Displacement: " << maxDisplacement <<
+    //         " Aspect Ratio " << maxRatio);
 
     // ---------------------------------------
     // new nodes positions are computed,
@@ -4568,7 +4571,11 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         std::swap( itNN[0],    itNN[1] );
         std::swap( prevNod[0], prevNod[1] );
         std::swap( nextNod[0], nextNod[1] );
+#if defined(__APPLE__)
+        std::swap( isSingleNode[0], isSingleNode[1] );
+#else
         isSingleNode.swap( isSingleNode[0], isSingleNode[1] );
+#endif
         if ( nbSame > 0 )
           sames[0] = 1 - sames[0];
         iNotSameNode = 1 - iNotSameNode;
@@ -6091,7 +6098,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       aPrms.push_back( aT );
     }
     //Extrusion_Error err =
-    MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
+    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
   } else if( aS.ShapeType() == TopAbs_WIRE ) {
     list< SMESH_subMesh* > LSM;
     TopTools_SequenceOfShape Edges;
@@ -6136,7 +6143,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         }
         list<SMESH_MeshEditor_PathPoint> LPP;
         //Extrusion_Error err =
-        MakeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
+        makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
         LLPPs.push_back(LPP);
         UsedNums.Add(k);
         // update startN for search following egde
@@ -6179,7 +6186,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     return EXTR_BAD_PATH_SHAPE;
   }
 
-  return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
+  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
                           theHasRefPoint, theRefPoint, theMakeGroups);
 }
 
@@ -6318,7 +6325,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
       list<SMESH_MeshEditor_PathPoint> LPP;
       aPrms.clear();
-      MakeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
+      makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
       LLPPs.push_back(LPP);
       if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i  ]->GetID();
       else                                        startNid = aNodesList[i-1]->GetID();
@@ -6376,7 +6383,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       aPrms.push_back( aT );
     }
     //Extrusion_Error err =
-    MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
+    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
   }
   else if( aS.ShapeType() == TopAbs_WIRE ) {
     list< SMESH_subMesh* > LSM;
@@ -6435,7 +6442,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         }
         list<SMESH_MeshEditor_PathPoint> LPP;
         //Extrusion_Error err =
-        MakeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
+        makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
         LLPPs.push_back(LPP);
         UsedNums.Add(k);
         // update startN for search following egde
@@ -6471,17 +6478,17 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     return EXTR_BAD_PATH_SHAPE;
   }
 
-  return MakeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
+  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
                           theHasRefPoint, theRefPoint, theMakeGroups);
 }
 
 
 //=======================================================================
-//function : MakeEdgePathPoints
-//purpose  : auxilary for ExtrusionAlongTrack
+//function : makeEdgePathPoints
+//purpose  : auxiliary for ExtrusionAlongTrack
 //=======================================================================
 SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>&                aPrms,
+SMESH_MeshEditor::makeEdgePathPoints(std::list<double>&                aPrms,
                                      const TopoDS_Edge&                aTrackEdge,
                                      bool                              FirstIsStart,
                                      list<SMESH_MeshEditor_PathPoint>& LPP)
@@ -6532,11 +6539,11 @@ SMESH_MeshEditor::MakeEdgePathPoints(std::list<double>&                aPrms,
 
 
 //=======================================================================
-//function : MakeExtrElements
-//purpose  : auxilary for ExtrusionAlongTrack
+//function : makeExtrElements
+//purpose  : auxiliary for ExtrusionAlongTrack
 //=======================================================================
 SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets[2],
+SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets[2],
                                    list<SMESH_MeshEditor_PathPoint>& fullList,
                                    const bool                        theHasAngles,
                                    list<double>&                     theAngles,
@@ -6549,7 +6556,7 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
 
   // Angles
   if( theHasAngles && !theAngles.empty() && theLinearVariation )
-    LinearAngleVariation(aNbTP-1, theAngles);
+    linearAngleVariation(aNbTP-1, theAngles);
 
   // fill vector of path points with angles
   vector<SMESH_MeshEditor_PathPoint> aPPs;
@@ -6742,11 +6749,11 @@ SMESH_MeshEditor::MakeExtrElements(TIDSortedElemSet                  theElemSets
 
 
 //=======================================================================
-//function : LinearAngleVariation
+//function : linearAngleVariation
 //purpose  : spread values over nbSteps
 //=======================================================================
 
-void SMESH_MeshEditor::LinearAngleVariation(const int     nbSteps,
+void SMESH_MeshEditor::linearAngleVariation(const int     nbSteps,
                                             list<double>& Angles)
 {
   int nbAngles = Angles.size();
@@ -7254,7 +7261,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
       }
     else
       while ( nIt->more() )
-        theNodes.insert( theNodes.end(),nIt->next() );
+        theNodes.insert( theNodes.end(), nIt->next() );
   }
   else if ( theSeparateCornersAndMedium ) // separate corners from medium nodes
   {
@@ -7341,16 +7348,18 @@ int SMESH_MeshEditor::SimplifyFace (const vector<const SMDS_MeshNode *>& faceNod
 //           in all elements.
 //=======================================================================
 
-void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
+void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
+                                   const bool           theAvoidMakingHoles)
 {
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
 
-  SMESHDS_Mesh* aMesh = GetMeshDS();
+  SMESHDS_Mesh* mesh = GetMeshDS();
 
   TNodeNodeMap nodeNodeMap; // node to replace - new node
   set<const SMDS_MeshElement*> elems; // all elements with changed nodes
   list< int > rmElemIds, rmNodeIds;
+  vector< ElemFeatures > newElemDefs;
 
   // Fill nodeNodeMap and elems
 
@@ -7364,17 +7373,6 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
     {
       const SMDS_MeshNode* nToRemove = *nIt;
       nodeNodeMap.insert( make_pair( nToRemove, nToKeep ));
-      if ( nToRemove != nToKeep )
-      {
-        rmNodeIds.push_back( nToRemove->GetID() );
-        AddToSameGroups( nToKeep, nToRemove, aMesh );
-        // set _alwaysComputed to a sub-mesh of VERTEX to enable mesh computing
-        // after MergeNodes() w/o creating node in place of merged ones.
-        const SMDS_PositionPtr& pos = nToRemove->GetPosition();
-        if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
-          if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
-            sm->SetIsAlwaysComputed( true );
-      }
       SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
       while ( invElemIt->more() ) {
         const SMDS_MeshElement* elem = invElemIt->next();
@@ -7382,469 +7380,568 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
       }
     }
   }
-  // Change element nodes or remove an element
 
-  set<const SMDS_MeshNode*> nodeSet;
-  vector< const SMDS_MeshNode*> curNodes, uniqueNodes;
-  vector<int> iRepl;
-  ElemFeatures elemType;
+  // Apply recursive replacements (BUG 0020185)
+  TNodeNodeMap::iterator nnIt = nodeNodeMap.begin();
+  for ( ; nnIt != nodeNodeMap.end(); ++nnIt )
+  {
+    const SMDS_MeshNode* nToKeep = nnIt->second;
+    TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep );
+    while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second )
+      nToKeep = nnIt_i->second;
+    nnIt->second = nToKeep;
+  }
+
+  if ( theAvoidMakingHoles )
+  {
+    // find elements whose topology changes
+
+    vector<const SMDS_MeshElement*> pbElems;
+    set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
+    for ( ; eIt != elems.end(); ++eIt )
+    {
+      const SMDS_MeshElement* elem = *eIt;
+      SMDS_ElemIteratorPtr     itN = elem->nodesIterator();
+      while ( itN->more() )
+      {
+        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() );
+        TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
+        if ( nnIt != nodeNodeMap.end() && elem->GetNodeIndex( nnIt->second ) >= 0 )
+        {
+          // several nodes of elem stick
+          pbElems.push_back( elem );
+          break;
+        }
+      }
+    }
+    // exclude from merge nodes causing spoiling element
+    for ( size_t iLoop = 0; iLoop < pbElems.size(); ++iLoop ) // avoid infinite cycle
+    {
+      bool nodesExcluded = false;
+      for ( size_t i = 0; i < pbElems.size(); ++i )
+      {
+        size_t prevNbMergeNodes = nodeNodeMap.size();
+        if ( !applyMerge( pbElems[i], newElemDefs, nodeNodeMap, /*noHoles=*/true ) &&
+             prevNbMergeNodes < nodeNodeMap.size() )
+          nodesExcluded = true;
+      }
+      if ( !nodesExcluded )
+        break;
+    }
+  }
+
+  for ( nnIt = nodeNodeMap.begin(); nnIt != nodeNodeMap.end(); ++nnIt )
+  {
+    const SMDS_MeshNode* nToRemove = nnIt->first;
+    const SMDS_MeshNode* nToKeep   = nnIt->second;
+    if ( nToRemove != nToKeep )
+    {
+      rmNodeIds.push_back( nToRemove->GetID() );
+      AddToSameGroups( nToKeep, nToRemove, mesh );
+      // set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing
+      // w/o creating node in place of merged ones.
+      const SMDS_PositionPtr& pos = nToRemove->GetPosition();
+      if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
+        if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
+          sm->SetIsAlwaysComputed( true );
+    }
+  }
+
+  // Change element nodes or remove an element
 
   set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
   for ( ; eIt != elems.end(); eIt++ )
   {
     const SMDS_MeshElement* elem = *eIt;
-    const           int  nbNodes = elem->NbNodes();
-    const           int aShapeId = FindShape( elem );
-    SMDSAbs_EntityType    entity = elem->GetEntityType();
+    SMESHDS_SubMesh*          sm = mesh->MeshElements( elem->getshapeId() );
 
-    nodeSet.clear();
-    curNodes.resize( nbNodes );
-    uniqueNodes.resize( nbNodes );
-    iRepl.resize( nbNodes );
-    int iUnique = 0, iCur = 0, nbRepl = 0;
+    bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false );
+    if ( !keepElem )
+      rmElemIds.push_back( elem->GetID() );
 
-    // get new seq of nodes
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() )
-    {
-      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() );
-
-      TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
-      if ( nnIt != nodeNodeMap.end() ) { // n sticks
-        n = (*nnIt).second;
-        { ////////// BUG 0020185: begin
-          bool stopRecur = false;
-          set<const SMDS_MeshNode*> nodesRecur;
-          nodesRecur.insert(n);
-          while (!stopRecur) {
-            TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( n );
-            if ( nnIt_i != nodeNodeMap.end() ) { // n sticks
-              n = (*nnIt_i).second;
-              if (!nodesRecur.insert(n).second) {
-                // error: recursive dependency
-                stopRecur = true;
-              }
-            }
-            else
-              stopRecur = true;
-          }
-        } ////////// BUG 0020185: end
+    for ( size_t i = 0; i < newElemDefs.size(); ++i )
+    {
+      if ( i > 0 || !mesh->ChangeElementNodes( elem,
+                                               & newElemDefs[i].myNodes[0],
+                                               newElemDefs[i].myNodes.size() ))
+      {
+        if ( i == 0 )
+        {
+          newElemDefs[i].SetID( elem->GetID() );
+          mesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
+          if ( !keepElem ) rmElemIds.pop_back();
+        }
+        else
+        {
+          newElemDefs[i].SetID( -1 );
+        }
+        SMDS_MeshElement* newElem = this->AddElement( newElemDefs[i].myNodes, newElemDefs[i] );
+        if ( sm && newElem )
+          sm->AddElement( newElem );
+        if ( elem != newElem )
+          ReplaceElemInGroups( elem, newElem, mesh );
       }
-      curNodes[ iCur ] = n;
-      bool isUnique = nodeSet.insert( n ).second;
-      if ( isUnique )
-        uniqueNodes[ iUnique++ ] = n;
-      else
-        iRepl[ nbRepl++ ] = iCur;
-      iCur++;
     }
+  }
+
+  // Remove bad elements, then equal nodes (order important)
+  Remove( rmElemIds, /*isNodes=*/false );
+  Remove( rmNodeIds, /*isNodes=*/true );
+
+  return;
+}
+
+//=======================================================================
+//function : applyMerge
+//purpose  : Compute new connectivity of an element after merging nodes
+//  \param [in] elems - the element
+//  \param [out] newElemDefs - definition(s) of result element(s)
+//  \param [inout] nodeNodeMap - nodes to merge
+//  \param [in] avoidMakingHoles - if true and and the element becomes invalid
+//              after merging (but not degenerated), removes nodes causing
+//              the invalidity from \a nodeNodeMap.
+//  \return bool - true if the element should be removed
+//=======================================================================
+
+bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
+                                   vector< ElemFeatures >& newElemDefs,
+                                   TNodeNodeMap&           nodeNodeMap,
+                                   const bool              avoidMakingHoles )
+{
+  bool toRemove = false; // to remove elem
+  int nbResElems = 1;    // nb new elements
+
+  newElemDefs.resize(nbResElems);
+  newElemDefs[0].Init( elem );
+  newElemDefs[0].myNodes.clear();
+
+  set<const SMDS_MeshNode*> nodeSet;
+  vector< const SMDS_MeshNode*>   curNodes;
+  vector< const SMDS_MeshNode*> & uniqueNodes = newElemDefs[0].myNodes;
+  vector<int> iRepl;
+
+  const        int  nbNodes = elem->NbNodes();
+  SMDSAbs_EntityType entity = elem->GetEntityType();
+
+  curNodes.resize( nbNodes );
+  uniqueNodes.resize( nbNodes );
+  iRepl.resize( nbNodes );
+  int iUnique = 0, iCur = 0, nbRepl = 0;
 
-    // Analyse element topology after replacement
+  // Get new seq of nodes
+
+  SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+  while ( itN->more() )
+  {
+    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( itN->next() );
+
+    TNodeNodeMap::iterator nnIt = nodeNodeMap.find( n );
+    if ( nnIt != nodeNodeMap.end() ) {
+      n = (*nnIt).second;
+    }
+    curNodes[ iCur ] = n;
+    bool isUnique = nodeSet.insert( n ).second;
+    if ( isUnique )
+      uniqueNodes[ iUnique++ ] = n;
+    else
+      iRepl[ nbRepl++ ] = iCur;
+    iCur++;
+  }
 
-    bool isOk = true;
-    int nbUniqueNodes = nodeSet.size();
-    if ( nbNodes != nbUniqueNodes ) // some nodes stick
+  // Analyse element topology after replacement
+
+  int nbUniqueNodes = nodeSet.size();
+  if ( nbNodes != nbUniqueNodes ) // some nodes stick
+  {
+    toRemove = true;
+    nbResElems = 0;
+
+    if ( newElemDefs[0].myIsQuad && newElemDefs[0].myType == SMDSAbs_Face && nbNodes > 6 )
     {
-      if ( elem->IsPoly() ) // Polygons and Polyhedral volumes
+      // if corner nodes stick, remove medium nodes between them from uniqueNodes
+      int nbCorners = nbNodes / 2;
+      for ( int iCur = 0; iCur < nbCorners; ++iCur )
       {
-        if ( elem->GetType() == SMDSAbs_Face ) // Polygon
+        int iNext = ( iCur + 1 ) % nbCorners;
+        if ( curNodes[ iCur ] == curNodes[ iNext ] ) // corners stick
         {
-          elemType.Init( elem );
-          const bool isQuad = elemType.myIsQuad;
-          if ( isQuad )
-            SMDS_MeshCell::applyInterlace // interlace medium and corner nodes
-              ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes );
-
-          // a polygon can divide into several elements
-          vector<const SMDS_MeshNode *> polygons_nodes;
-          vector<int> quantities;
-          int nbNew = SimplifyFace( curNodes, polygons_nodes, quantities );
-          if (nbNew > 0)
+          int iMedium = iCur + nbCorners;
+          vector< const SMDS_MeshNode* >::iterator i =
+            std::find( uniqueNodes.begin() + nbCorners - nbRepl,
+                       uniqueNodes.end(),
+                       curNodes[ iMedium ]);
+          if ( i != uniqueNodes.end() )
           {
-            vector<const SMDS_MeshNode *> face_nodes;
-            int inode = 0;
-            for (int iface = 0; iface < nbNew; iface++)
-            {
-              int nbNewNodes = quantities[iface];
-              face_nodes.assign( polygons_nodes.begin() + inode,
-                                 polygons_nodes.begin() + inode + nbNewNodes );
-              inode += nbNewNodes;
-              if ( isQuad ) // check if a result elem is a valid quadratic polygon
-              {
-                bool isValid = ( nbNewNodes % 2 == 0 );
-                for ( int i = 0; i < nbNewNodes && isValid; ++i )
-                  isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 ));
-                elemType.SetQuad( isValid );
-                if ( isValid ) // put medium nodes after corners
-                  SMDS_MeshCell::applyInterlaceRev
-                    ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
-                                                          nbNewNodes ), face_nodes );
-              }
-              elemType.SetPoly(( nbNewNodes / ( elemType.myIsQuad + 1 ) > 4 ));
-
-              SMDS_MeshElement* newElem = AddElement( face_nodes, elemType.SetID(-1));
-              if ( aShapeId )
-                aMesh->SetMeshElementOnShape(newElem, aShapeId);
-            }
+            --nbUniqueNodes;
+            for ( ; i+1 != uniqueNodes.end(); ++i )
+              *i = *(i+1);
           }
-          rmElemIds.push_back(elem->GetID());
+        }
+      }
+    }
 
-        } // Polygon
+    switch ( entity )
+    {
+    case SMDSEntity_Polygon:
+    case SMDSEntity_Quad_Polygon: // Polygon
+    {
+      ElemFeatures* elemType = & newElemDefs[0];
+      const bool isQuad = elemType->myIsQuad;
+      if ( isQuad )
+        SMDS_MeshCell::applyInterlace // interlace medium and corner nodes
+          ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon, nbNodes ), curNodes );
 
-        else if ( elem->GetType() == SMDSAbs_Volume ) // Polyhedral volume
-        {
-          if ( nbUniqueNodes < 4 ) {
-            rmElemIds.push_back(elem->GetID());
-          }
-          else {
-            // each face has to be analyzed in order to check volume validity
-            const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
-            if ( aPolyedre )
-            {
-              int nbFaces = aPolyedre->NbFaces();
+      // a polygon can divide into several elements
+      vector<const SMDS_MeshNode *> polygons_nodes;
+      vector<int> quantities;
+      nbResElems = SimplifyFace( curNodes, polygons_nodes, quantities );
+      newElemDefs.resize( nbResElems );
+      for ( int inode = 0, iface = 0; iface < nbResElems; iface++ )
+      {
+        ElemFeatures* elemType = & newElemDefs[iface];
+        if ( iface ) elemType->Init( elem );
 
-              vector<const SMDS_MeshNode *> poly_nodes;
-              vector<int>                   quantities;
-              vector<const SMDS_MeshNode *> faceNodes;
+        vector<const SMDS_MeshNode *>& face_nodes = elemType->myNodes;
+        int nbNewNodes = quantities[iface];
+        face_nodes.assign( polygons_nodes.begin() + inode,
+                           polygons_nodes.begin() + inode + nbNewNodes );
+        inode += nbNewNodes;
+        if ( isQuad ) // check if a result elem is a valid quadratic polygon
+        {
+          bool isValid = ( nbNewNodes % 2 == 0 );
+          for ( int i = 0; i < nbNewNodes && isValid; ++i )
+            isValid = ( elem->IsMediumNode( face_nodes[i]) == bool( i % 2 ));
+          elemType->SetQuad( isValid );
+          if ( isValid ) // put medium nodes after corners
+            SMDS_MeshCell::applyInterlaceRev
+              ( SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Quad_Polygon,
+                                                    nbNewNodes ), face_nodes );
+        }
+        elemType->SetPoly(( nbNewNodes / ( elemType->myIsQuad + 1 ) > 4 ));
+      }
+      nbUniqueNodes = newElemDefs[0].myNodes.size();
+      break;
+    } // Polygon
 
-              for (int iface = 1; iface <= nbFaces; iface++)
-              {
-                int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
-                faceNodes.resize( nbFaceNodes );
-                for (int inode = 1; inode <= nbFaceNodes; inode++)
-                {
-                  const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode);
-                  TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode);
-                  if ( nnIt != nodeNodeMap.end() ) // faceNode sticks
-                    faceNode = (*nnIt).second;
-                  faceNodes[inode - 1] = faceNode;
-                }
-                SimplifyFace(faceNodes, poly_nodes, quantities);
-              }
+    case SMDSEntity_Polyhedra: // Polyhedral volume
+    {
+      if ( nbUniqueNodes >= 4 )
+      {
+        // each face has to be analyzed in order to check volume validity
+        if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ))
+        {
+          int nbFaces = aPolyedre->NbFaces();
 
-              if ( quantities.size() > 3 ) {
-                // TODO: remove coincident faces
-              }
+          vector<const SMDS_MeshNode *>& poly_nodes = newElemDefs[0].myNodes;
+          vector<int>                  & quantities = newElemDefs[0].myPolyhedQuantities;
+          vector<const SMDS_MeshNode *>  faceNodes;
+          poly_nodes.clear();
+          quantities.clear();
 
-              if ( quantities.size() > 3 )
-              {
-                const SMDS_MeshElement* newElem =
-                  aMesh->AddPolyhedralVolume( poly_nodes, quantities );
-                myLastCreatedElems.Append( newElem );
-                if ( aShapeId && newElem )
-                  aMesh->SetMeshElementOnShape( newElem, aShapeId );
-                rmElemIds.push_back( elem->GetID() );
-              }
-            }
-            else {
-              rmElemIds.push_back( elem->GetID() );
+          for (int iface = 1; iface <= nbFaces; iface++)
+          {
+            int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
+            faceNodes.resize( nbFaceNodes );
+            for (int inode = 1; inode <= nbFaceNodes; inode++)
+            {
+              const SMDS_MeshNode * faceNode = aPolyedre->GetFaceNode(iface, inode);
+              TNodeNodeMap::iterator nnIt = nodeNodeMap.find(faceNode);
+              if ( nnIt != nodeNodeMap.end() ) // faceNode sticks
+                faceNode = (*nnIt).second;
+              faceNodes[inode - 1] = faceNode;
             }
+            SimplifyFace(faceNodes, poly_nodes, quantities);
           }
-        }
-        else {
-        }
-
-        continue;
-      } // poly element
 
-      // Regular elements
-      // TODO not all the possible cases are solved. Find something more generic?
-      switch ( entity ) {
-      case SMDSEntity_Edge: //////// EDGE
-      case SMDSEntity_Triangle: //// TRIANGLE
-      case SMDSEntity_Quad_Triangle:
-      case SMDSEntity_Tetra:
-      case SMDSEntity_Quad_Tetra: // TETRAHEDRON
-      {
-        isOk = false;
-        break;
+          if ( quantities.size() > 3 )
+          {
+            // TODO: remove coincident faces
+            nbResElems = 1;
+            nbUniqueNodes = newElemDefs[0].myNodes.size();
+          }
+        }
       }
-      case SMDSEntity_Quad_Edge:
+    }
+    break;
+
+    // Regular elements
+    // TODO not all the possible cases are solved. Find something more generic?
+    case SMDSEntity_Edge: //////// EDGE
+    case SMDSEntity_Triangle: //// TRIANGLE
+    case SMDSEntity_Quad_Triangle:
+    case SMDSEntity_Tetra:
+    case SMDSEntity_Quad_Tetra: // TETRAHEDRON
+    {
+      break;
+    }
+    case SMDSEntity_Quad_Edge:
+    {
+      break;
+    }
+    case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE
+    {
+      if ( nbUniqueNodes < 3 )
+        toRemove = true;
+      else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ])
+        toRemove = true; // opposite nodes stick
+      else
+        toRemove = false;
+      break;
+    }
+    case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE
+    {
+      //   1    5    2
+      //    +---+---+
+      //    |       |
+      //   4+       +6
+      //    |       |
+      //    +---+---+
+      //   0    7    3
+      if ( nbUniqueNodes == 6 &&
+           iRepl[0] < 4       &&
+           ( nbRepl == 1 || iRepl[1] >= 4 ))
       {
-        isOk = false; // to linear EDGE ???????
-        break;
+        toRemove = false;
       }
-      case SMDSEntity_Quadrangle: //////////////////////////////////// QUADRANGLE
+      break;
+    }
+    case SMDSEntity_BiQuad_Quadrangle: // Bi-Quadratic QUADRANGLE
+    {
+      //   1    5    2
+      //    +---+---+
+      //    |       |
+      //   4+  8+   +6
+      //    |       |
+      //    +---+---+
+      //   0    7    3
+      if ( nbUniqueNodes == 7 &&
+           iRepl[0] < 4       &&
+           ( nbRepl == 1 || iRepl[1] != 8 ))
       {
-        if ( nbUniqueNodes < 3 )
-          isOk = false;
-        else if ( nbRepl == 1 && curNodes[ iRepl[0]] == curNodes[( iRepl[0]+2 )%4 ])
-          isOk = false; // opposite nodes stick
-        break;
+        toRemove = false;
       }
-      case SMDSEntity_Quad_Quadrangle: // Quadratic QUADRANGLE
-      {
-        //   1    5    2
-        //    +---+---+
-        //    |       |
-        //   4+       +6
-        //    |       |
-        //    +---+---+
-        //   0    7    3
-        if (( nbUniqueNodes == 6 && nbRepl == 2 ) &&
-            (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) ||
-             ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) ||
-             ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) ||
-             ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] )))
+      break;
+    }
+    case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON
+    {
+      if ( nbUniqueNodes == 4 ) {
+        // ---------------------------------> tetrahedron
+        if ( curNodes[3] == curNodes[4] &&
+             curNodes[3] == curNodes[5] ) {
+          // top nodes stick
+          toRemove = false;
+        }
+        else if ( curNodes[0] == curNodes[1] &&
+                  curNodes[0] == curNodes[2] ) {
+          // bottom nodes stick: set a top before
+          uniqueNodes[ 3 ] = uniqueNodes [ 0 ];
+          uniqueNodes[ 0 ] = curNodes [ 5 ];
+          uniqueNodes[ 1 ] = curNodes [ 4 ];
+          uniqueNodes[ 2 ] = curNodes [ 3 ];
+          toRemove = false;
+        }
+        else if (( curNodes[0] == curNodes[3] ) +
+                 ( curNodes[1] == curNodes[4] ) +
+                 ( curNodes[2] == curNodes[5] ) == 2 ) {
+          // a lateral face turns into a line
+          toRemove = false;
+        }
+      }
+      else if ( nbUniqueNodes == 5 ) {
+        // PENTAHEDRON --------------------> pyramid
+        if ( curNodes[0] == curNodes[3] )
         {
-          isOk = true;
-        }
-        break;
-      }
-      case SMDSEntity_BiQuad_Quadrangle: // Bi-Quadratic QUADRANGLE
-      {
-        //   1    5    2
-        //    +---+---+
-        //    |       |
-        //   4+  8+   +6
-        //    |       |
-        //    +---+---+
-        //   0    7    3
-        if (( nbUniqueNodes == 7 && nbRepl == 2 && iRepl[1] != 8 ) &&
-            (( iRepl[0] == 1 && iRepl[1] == 4 && curNodes[1] == curNodes[0] ) ||
-             ( iRepl[0] == 2 && iRepl[1] == 5 && curNodes[2] == curNodes[1] ) ||
-             ( iRepl[0] == 3 && iRepl[1] == 6 && curNodes[3] == curNodes[2] ) ||
-             ( iRepl[0] == 3 && iRepl[1] == 7 && curNodes[3] == curNodes[0] )))
+          uniqueNodes[ 0 ] = curNodes[ 1 ];
+          uniqueNodes[ 1 ] = curNodes[ 4 ];
+          uniqueNodes[ 2 ] = curNodes[ 5 ];
+          uniqueNodes[ 3 ] = curNodes[ 2 ];
+          uniqueNodes[ 4 ] = curNodes[ 0 ];
+          toRemove = false;
+        }
+        if ( curNodes[1] == curNodes[4] )
         {
-          isOk = true;
-        }
-        break;
-      }
-      case SMDSEntity_Penta: ///////////////////////////////////// PENTAHEDRON
-      {
-        isOk = false;
-        if ( nbUniqueNodes == 4 ) {
-          // ---------------------------------> tetrahedron
-          if ( curNodes[3] == curNodes[4] &&
-               curNodes[3] == curNodes[5] ) {
-            // top nodes stick
-            isOk = true;
-          }
-          else if ( curNodes[0] == curNodes[1] &&
-                    curNodes[0] == curNodes[2] ) {
-            // bottom nodes stick: set a top before
-            uniqueNodes[ 3 ] = uniqueNodes [ 0 ];
-            uniqueNodes[ 0 ] = curNodes [ 5 ];
-            uniqueNodes[ 1 ] = curNodes [ 4 ];
-            uniqueNodes[ 2 ] = curNodes [ 3 ];
-            isOk = true;
-          }
-          else if (( curNodes[0] == curNodes[3] ) +
-                   ( curNodes[1] == curNodes[4] ) +
-                   ( curNodes[2] == curNodes[5] ) == 2 ) {
-            // a lateral face turns into a line
-            isOk = true;
-          }
-        }
-        else if ( nbUniqueNodes == 5 ) {
-          // PENTAHEDRON --------------------> pyramid
-          if ( curNodes[0] == curNodes[3] )
-          {
-            uniqueNodes[ 0 ] = curNodes[ 1 ];
-            uniqueNodes[ 1 ] = curNodes[ 4 ];
-            uniqueNodes[ 2 ] = curNodes[ 5 ];
-            uniqueNodes[ 3 ] = curNodes[ 2 ];
-            uniqueNodes[ 4 ] = curNodes[ 0 ];
-            isOk = true;
-          }
-          if ( curNodes[1] == curNodes[4] )
-          {
-            uniqueNodes[ 0 ] = curNodes[ 0 ];
-            uniqueNodes[ 1 ] = curNodes[ 2 ];
-            uniqueNodes[ 2 ] = curNodes[ 5 ];
-            uniqueNodes[ 3 ] = curNodes[ 3 ];
-            uniqueNodes[ 4 ] = curNodes[ 1 ];
-            isOk = true;
-          }
-          if ( curNodes[2] == curNodes[5] )
-          {
-            uniqueNodes[ 0 ] = curNodes[ 0 ];
-            uniqueNodes[ 1 ] = curNodes[ 3 ];
-            uniqueNodes[ 2 ] = curNodes[ 4 ];
-            uniqueNodes[ 3 ] = curNodes[ 1 ];
-            uniqueNodes[ 4 ] = curNodes[ 2 ];
-            isOk = true;
-          }
+          uniqueNodes[ 0 ] = curNodes[ 0 ];
+          uniqueNodes[ 1 ] = curNodes[ 2 ];
+          uniqueNodes[ 2 ] = curNodes[ 5 ];
+          uniqueNodes[ 3 ] = curNodes[ 3 ];
+          uniqueNodes[ 4 ] = curNodes[ 1 ];
+          toRemove = false;
+        }
+        if ( curNodes[2] == curNodes[5] )
+        {
+          uniqueNodes[ 0 ] = curNodes[ 0 ];
+          uniqueNodes[ 1 ] = curNodes[ 3 ];
+          uniqueNodes[ 2 ] = curNodes[ 4 ];
+          uniqueNodes[ 3 ] = curNodes[ 1 ];
+          uniqueNodes[ 4 ] = curNodes[ 2 ];
+          toRemove = false;
         }
-        break;
       }
-      case SMDSEntity_Hexa:
-      {
-        //////////////////////////////////// HEXAHEDRON
-        isOk = false;
-        SMDS_VolumeTool hexa (elem);
-        hexa.SetExternalNormal();
-        if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
-          //////////////////////// HEX ---> tetrahedron
-          for ( int iFace = 0; iFace < 6; iFace++ ) {
-            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
-            if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
-                curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
-                curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
-              // one face turns into a point ...
-              int  pickInd = ind[ 0 ];
-              int iOppFace = hexa.GetOppFaceIndex( iFace );
-              ind = hexa.GetFaceNodesIndices( iOppFace );
-              int nbStick = 0;
-              uniqueNodes.clear();
-              for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
-                if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
-                  nbStick++;
-                else
-                  uniqueNodes.push_back( curNodes[ind[ iCur ]]);
-              }
-              if ( nbStick == 1 ) {
-                // ... and the opposite one - into a triangle.
-                // set a top node
-                uniqueNodes.push_back( curNodes[ pickInd ]);
-                isOk = true;
-              }
-              break;
+      break;
+    }
+    case SMDSEntity_Hexa:
+    {
+      //////////////////////////////////// HEXAHEDRON
+      SMDS_VolumeTool hexa (elem);
+      hexa.SetExternalNormal();
+      if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
+        //////////////////////// HEX ---> tetrahedron
+        for ( int iFace = 0; iFace < 6; iFace++ ) {
+          const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
+          if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
+              curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
+              curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
+            // one face turns into a point ...
+            int  pickInd = ind[ 0 ];
+            int iOppFace = hexa.GetOppFaceIndex( iFace );
+            ind = hexa.GetFaceNodesIndices( iOppFace );
+            int nbStick = 0;
+            uniqueNodes.clear();
+            for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
+              if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
+                nbStick++;
+              else
+                uniqueNodes.push_back( curNodes[ind[ iCur ]]);
+            }
+            if ( nbStick == 1 ) {
+              // ... and the opposite one - into a triangle.
+              // set a top node
+              uniqueNodes.push_back( curNodes[ pickInd ]);
+              toRemove = false;
             }
-          }
-        }
-        else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
-          //////////////////////// HEX ---> prism
-          int nbTria = 0, iTria[3];
-          const int *ind; // indices of face nodes
-          // look for triangular faces
-          for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
-            ind = hexa.GetFaceNodesIndices( iFace );
-            TIDSortedNodeSet faceNodes;
-            for ( iCur = 0; iCur < 4; iCur++ )
-              faceNodes.insert( curNodes[ind[iCur]] );
-            if ( faceNodes.size() == 3 )
-              iTria[ nbTria++ ] = iFace;
-          }
-          // check if triangles are opposite
-          if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
-          {
-            // set nodes of the bottom triangle
-            ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
-            vector<int> indB;
-            for ( iCur = 0; iCur < 4; iCur++ )
-              if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
-                indB.push_back( ind[iCur] );
-            if ( !hexa.IsForward() )
-              std::swap( indB[0], indB[2] );
-            for ( iCur = 0; iCur < 3; iCur++ )
-              uniqueNodes[ iCur ] = curNodes[indB[iCur]];
-            // set nodes of the top triangle
-            const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
-            for ( iCur = 0; iCur < 3; ++iCur )
-              for ( int j = 0; j < 4; ++j )
-                if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
-                {
-                  uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
-                  break;
-                }
-            isOk = true;
             break;
           }
         }
-        else if (nbUniqueNodes == 5 && nbRepl == 3 ) {
-          //////////////////// HEXAHEDRON ---> pyramid
-          for ( int iFace = 0; iFace < 6; iFace++ ) {
-            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
-            if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
-                curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
-                curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
-              // one face turns into a point ...
-              int iOppFace = hexa.GetOppFaceIndex( iFace );
-              ind = hexa.GetFaceNodesIndices( iOppFace );
-              uniqueNodes.clear();
-              for ( iCur = 0; iCur < 4; iCur++ ) {
-                if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
-                  break;
-                else
-                  uniqueNodes.push_back( curNodes[ind[ iCur ]]);
-              }
-              if ( uniqueNodes.size() == 4 ) {
-                // ... and the opposite one is a quadrangle
-                // set a top node
-                const int* indTop = hexa.GetFaceNodesIndices( iFace );
-                uniqueNodes.push_back( curNodes[indTop[ 0 ]]);
-                isOk = true;
+      }
+      else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
+        //////////////////////// HEX ---> prism
+        int nbTria = 0, iTria[3];
+        const int *ind; // indices of face nodes
+        // look for triangular faces
+        for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
+          ind = hexa.GetFaceNodesIndices( iFace );
+          TIDSortedNodeSet faceNodes;
+          for ( iCur = 0; iCur < 4; iCur++ )
+            faceNodes.insert( curNodes[ind[iCur]] );
+          if ( faceNodes.size() == 3 )
+            iTria[ nbTria++ ] = iFace;
+        }
+        // check if triangles are opposite
+        if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
+        {
+          // set nodes of the bottom triangle
+          ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
+          vector<int> indB;
+          for ( iCur = 0; iCur < 4; iCur++ )
+            if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
+              indB.push_back( ind[iCur] );
+          if ( !hexa.IsForward() )
+            std::swap( indB[0], indB[2] );
+          for ( iCur = 0; iCur < 3; iCur++ )
+            uniqueNodes[ iCur ] = curNodes[indB[iCur]];
+          // set nodes of the top triangle
+          const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
+          for ( iCur = 0; iCur < 3; ++iCur )
+            for ( int j = 0; j < 4; ++j )
+              if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
+              {
+                uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
+                break;
               }
-              break;
+          toRemove = false;
+          break;
+        }
+      }
+      else if (nbUniqueNodes == 5 && nbRepl == 3 ) {
+        //////////////////// HEXAHEDRON ---> pyramid
+        for ( int iFace = 0; iFace < 6; iFace++ ) {
+          const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
+          if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
+              curNodes[ind[ 0 ]] == curNodes[ind[ 2 ]] &&
+              curNodes[ind[ 0 ]] == curNodes[ind[ 3 ]] ) {
+            // one face turns into a point ...
+            int iOppFace = hexa.GetOppFaceIndex( iFace );
+            ind = hexa.GetFaceNodesIndices( iOppFace );
+            uniqueNodes.clear();
+            for ( iCur = 0; iCur < 4; iCur++ ) {
+              if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
+                break;
+              else
+                uniqueNodes.push_back( curNodes[ind[ iCur ]]);
             }
+            if ( uniqueNodes.size() == 4 ) {
+              // ... and the opposite one is a quadrangle
+              // set a top node
+              const int* indTop = hexa.GetFaceNodesIndices( iFace );
+              uniqueNodes.push_back( curNodes[indTop[ 0 ]]);
+              toRemove = false;
+            }
+            break;
           }
         }
+      }
 
-        if ( !isOk && nbUniqueNodes > 4 ) {
-          ////////////////// HEXAHEDRON ---> polyhedron
-          hexa.SetExternalNormal();
-          vector<const SMDS_MeshNode *> poly_nodes; poly_nodes.reserve( 6 * 4 );
-          vector<int>                   quantities; quantities.reserve( 6 );
-          for ( int iFace = 0; iFace < 6; iFace++ )
+      if ( toRemove && nbUniqueNodes > 4 ) {
+        ////////////////// HEXAHEDRON ---> polyhedron
+        hexa.SetExternalNormal();
+        vector<const SMDS_MeshNode *>& poly_nodes = newElemDefs[0].myNodes;
+        vector<int>                  & quantities = newElemDefs[0].myPolyhedQuantities;
+        poly_nodes.reserve( 6 * 4 ); poly_nodes.clear();
+        quantities.reserve( 6 );     quantities.clear();
+        for ( int iFace = 0; iFace < 6; iFace++ )
+        {
+          const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
+          if ( curNodes[ind[0]] == curNodes[ind[2]] ||
+               curNodes[ind[1]] == curNodes[ind[3]] )
           {
-            const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
-            if ( curNodes[ind[0]] == curNodes[ind[2]] ||
-                 curNodes[ind[1]] == curNodes[ind[3]] )
-            {
-              quantities.clear();
-              break; // opposite nodes stick
-            }
-            nodeSet.clear();
-            for ( iCur = 0; iCur < 4; iCur++ )
-            {
-              if ( nodeSet.insert( curNodes[ind[ iCur ]] ).second )
-                poly_nodes.push_back( curNodes[ind[ iCur ]]);
-            }
-            if ( nodeSet.size() < 3 )
-              poly_nodes.resize( poly_nodes.size() - nodeSet.size() );
-            else
-              quantities.push_back( nodeSet.size() );
+            quantities.clear();
+            break; // opposite nodes stick
           }
-          if ( quantities.size() >= 4 )
+          nodeSet.clear();
+          for ( iCur = 0; iCur < 4; iCur++ )
           {
-            const SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities );
-            myLastCreatedElems.Append( newElem );
-            if ( aShapeId && newElem )
-              aMesh->SetMeshElementOnShape( newElem, aShapeId );
-            rmElemIds.push_back( elem->GetID() );
+            if ( nodeSet.insert( curNodes[ind[ iCur ]] ).second )
+              poly_nodes.push_back( curNodes[ind[ iCur ]]);
           }
+          if ( nodeSet.size() < 3 )
+            poly_nodes.resize( poly_nodes.size() - nodeSet.size() );
+          else
+            quantities.push_back( nodeSet.size() );
         }
-        break;
-      } // case HEXAHEDRON
+        if ( quantities.size() >= 4 )
+        {
+          nbResElems = 1;
+          nbUniqueNodes = poly_nodes.size();
+          newElemDefs[0].SetPoly(true);
+        }
+      }
+      break;
+    } // case HEXAHEDRON
 
-      default:
-        isOk = false;
-      } // switch ( nbNodes )
+    default:
+      toRemove = true;
 
-    } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
+    } // switch ( entity )
 
-    if ( isOk ) // a non-poly elem remains valid after sticking nodes
+    if ( toRemove && nbResElems == 0 && avoidMakingHoles )
     {
-      if ( nbNodes != nbUniqueNodes ||
-           !aMesh->ChangeElementNodes( elem, & curNodes[0], nbNodes ))
-      {
-        elemType.Init( elem ).SetID( elem->GetID() );
-
-        SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
-        aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
-
-        uniqueNodes.resize(nbUniqueNodes);
-        SMDS_MeshElement* newElem = this->AddElement( uniqueNodes, elemType );
-        if ( sm && newElem )
-          sm->AddElement( newElem );
-        if ( elem != newElem )
-          ReplaceElemInGroups( elem, newElem, aMesh );
-      }
-    }
-    else {
-      // Remove invalid regular element or invalid polygon
-      rmElemIds.push_back( elem->GetID() );
+      // erase from nodeNodeMap nodes whose merge spoils elem
+      vector< const SMDS_MeshNode* > noMergeNodes;
+      SMESH_MeshAlgos::DeMerge( elem, curNodes, noMergeNodes );
+      for ( size_t i = 0; i < noMergeNodes.size(); ++i )
+        nodeNodeMap.erase( noMergeNodes[i] );
     }
+    
+  } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
 
-  } // loop on elements
+  uniqueNodes.resize( nbUniqueNodes );
 
-  // Remove bad elements, then equal nodes (order important)
+  if ( !toRemove && nbResElems == 0 )
+    nbResElems = 1;
 
-  Remove( rmElemIds, false );
-  Remove( rmNodeIds, true );
+  newElemDefs.resize( nbResElems );
 
-  return;
+  return !toRemove;
 }
 
 
@@ -8235,7 +8332,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     // -------------------------------------------------------------------------
 
     // 1. Since sewing may break if there are volumes to split on the side 2,
-    //    we wont move nodes but just compute new coordinates for them
+    //    we won't move nodes but just compute new coordinates for them
     typedef map<const SMDS_MeshNode*, gp_XYZ> TNodeXYZMap;
     TNodeXYZMap nBordXYZ;
     list< const SMDS_MeshNode* >& bordNodes = nSide[ 0 ];
@@ -8399,7 +8496,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
       } // loop on inverse elements of prevSideNode
 
       if ( !sideNode ) {
-        MESSAGE(" Cant find path by links of the Side 2 ");
+        MESSAGE(" Can't find path by links of the Side 2 ");
         return SEW_BAD_SIDE_NODES;
       }
       sideNodes.push_back( sideNode );
@@ -9197,7 +9294,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     // remove a linear element
     GetMeshDS()->RemoveFreeElement(elem, theSm, /*fromGroups=*/false);
 
-    // remove central nodes of biquadratic elements (biquad->quad convertion)
+    // remove central nodes of biquadratic elements (biquad->quad conversion)
     if ( hasCentralNodes )
       for ( size_t i = nbNodes * 2; i < nodes.size(); ++i )
         if ( nodes[i]->NbInverseElements() == 0 )
@@ -9845,7 +9942,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   //    face does not exist
 
   SMESHDS_Mesh* aMesh = GetMeshDS();
-  // TODO algoritm not OK with vtkUnstructuredGrid: 2 meshes can't share nodes
+  // TODO algorithm not OK with vtkUnstructuredGrid: 2 meshes can't share nodes
   //SMDS_Mesh aTmpFacesMesh; // try to use the same mesh
   TIDSortedElemSet             faceSet1, faceSet2;
   set<const SMDS_MeshElement*> volSet1,  volSet2;
@@ -11075,9 +11172,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                                                      bool                                 createJointElems,
                                                      bool                                 onAllBoundaries)
 {
-  MESSAGE("----------------------------------------------");
-  MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
-  MESSAGE("----------------------------------------------");
+  // MESSAGE("----------------------------------------------");
+  // MESSAGE("SMESH_MeshEditor::doubleNodesOnGroupBoundaries");
+  // MESSAGE("----------------------------------------------");
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
   meshDS->BuildDownWardConnectivity(true);
@@ -11100,7 +11197,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   std::set<int> emptySet;
   emptyMap.clear();
 
-  MESSAGE(".. Number of domains :"<<theElems.size());
+  //MESSAGE(".. Number of domains :"<<theElems.size());
 
   TIDSortedElemSet theRestDomElems;
   const int iRestDom  = -1;
@@ -11140,7 +11237,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
     //     and corresponding volume of this domain, for each shared face.
     //     a volume has a face shared by 2 domains if it has a neighbor which is not in his domain.
 
-    MESSAGE("... Neighbors of domain #" << idom);
+    //MESSAGE("... Neighbors of domain #" << idom);
     const TIDSortedElemSet& domain = theElems[idom];
     TIDSortedElemSet::const_iterator elemItr = domain.begin();
     for (; elemItr != domain.end(); ++elemItr)
@@ -11251,7 +11348,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   std::map<int, std::vector<int> > mutipleNodes; // nodes multi domains with domain order
   std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)
 
-  MESSAGE(".. Duplication of the nodes");
+  //MESSAGE(".. Duplication of the nodes");
   for (int idomain = idom0; idomain < nbDomains; idomain++)
   {
     itface = faceDomains.begin();
@@ -11312,7 +11409,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
     }
   }
 
-  MESSAGE(".. Creation of elements");
+  //MESSAGE(".. Creation of elements");
   for (int idomain = idom0; idomain < nbDomains; idomain++)
   {
     itface = faceDomains.begin();
@@ -11443,7 +11540,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   std::map<int, std::map<long,int> > nodeQuadDomains;
   std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
 
-  MESSAGE(".. Creation of elements: simple junction");
+  //MESSAGE(".. Creation of elements: simple junction");
   if (createJointElems)
   {
     int idg;
@@ -11494,7 +11591,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //     iterate on mutipleNodesToFace
   //     iterate on edgesMultiDomains
 
-  MESSAGE(".. Creation of elements: multiple junction");
+  //MESSAGE(".. Creation of elements: multiple junction");
   if (createJointElems)
   {
     // --- iterate on mutipleNodesToFace
@@ -11567,7 +11664,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   faceOrEdgeDom.clear();
   feDom.clear();
 
-  MESSAGE(".. Modification of elements");
+  //MESSAGE(".. Modification of elements");
   for (int idomain = idom0; idomain < nbDomains; idomain++)
   {
     std::map<int, std::map<int, int> >::const_iterator itnod = nodeDomains.begin();
@@ -11669,9 +11766,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
  */
 bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSortedElemSet>& theElems)
 {
-  MESSAGE("-------------------------------------------------");
-  MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
-  MESSAGE("-------------------------------------------------");
+  // MESSAGE("-------------------------------------------------");
+  // MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
+  // MESSAGE("-------------------------------------------------");
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
 
@@ -11833,9 +11930,9 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
                                       std::vector<double>&            nodesCoords,
                                       std::vector<std::vector<int> >& listOfListOfNodes)
 {
-  MESSAGE("--------------------------------");
-  MESSAGE("SMESH_MeshEditor::CreateHoleSkin");
-  MESSAGE("--------------------------------");
+  // MESSAGE("--------------------------------");
+  // MESSAGE("SMESH_MeshEditor::CreateHoleSkin");
+  // MESSAGE("--------------------------------");
 
   // --- zone of volumes to remove is given :
   //     1 either by a geom shape (one or more vertices) and a radius,
@@ -11937,7 +12034,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
 
   if (isNodeGroup) // --- a group of nodes is provided : find all the volumes using one or more of this nodes
   {
-    MESSAGE("group of nodes provided");
+    //MESSAGE("group of nodes provided");
     SMDS_ElemIteratorPtr elemIt = groupDS->GetElements();
     while ( elemIt->more() )
     {
@@ -11959,7 +12056,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   else if (isNodeCoords)
   {
-    MESSAGE("list of nodes coordinates provided");
+    //MESSAGE("list of nodes coordinates provided");
     size_t i = 0;
     int k = 0;
     while ( i < nodesCoords.size()-2 )
@@ -11969,13 +12066,13 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       double z = nodesCoords[i++];
       gp_Pnt p = gp_Pnt(x, y ,z);
       gpnts.push_back(p);
-      MESSAGE("TopoDS_Vertex " << k << " " << p.X() << " " << p.Y() << " " << p.Z());
+      //MESSAGE("TopoDS_Vertex " << k << " " << p.X() << " " << p.Y() << " " << p.Z());
       k++;
     }
   }
   else // --- no group, no coordinates : use the vertices of the geom shape provided, and radius
   {
-    MESSAGE("no group of nodes provided, using vertices from geom shape, and radius");
+    //MESSAGE("no group of nodes provided, using vertices from geom shape, and radius");
     TopTools_IndexedMapOfShape vertexMap;
     TopExp::MapShapes( theShape, TopAbs_VERTEX, vertexMap );
     gp_Pnt p = gp_Pnt(0,0,0);
@@ -11987,20 +12084,17 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       const TopoDS_Vertex& vertex = TopoDS::Vertex( vertexMap( i ));
       p = BRep_Tool::Pnt(vertex);
       gpnts.push_back(p);
-      MESSAGE("TopoDS_Vertex " << i << " " << p.X() << " " << p.Y() << " " << p.Z());
+      //MESSAGE("TopoDS_Vertex " << i << " " << p.X() << " " << p.Y() << " " << p.Z());
     }
   }
 
   if (gpnts.size() > 0)
   {
-    int nodeId = 0;
     const SMDS_MeshNode* startNode = theNodeSearcher->FindClosestTo(gpnts[0]);
-    if (startNode)
-      nodeId = startNode->GetID();
-    MESSAGE("nodeId " << nodeId);
+    //MESSAGE("startNode->nodeId " << nodeId);
 
     double radius2 = radius*radius;
-    MESSAGE("radius2 " << radius2);
+    //MESSAGE("radius2 " << radius2);
 
     // --- volumes on start node
 
@@ -12029,7 +12123,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     {
       std::set<int>::iterator it = setOfVolToCheck.begin();
       int vtkId = *it;
-      MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+      //MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
       bool volInside = false;
       vtkIdType npts = 0;
       vtkIdType* pts = 0;
@@ -12040,7 +12134,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         if (mapOfNodeDistance2.count(pts[i]))
         {
           distance2 = mapOfNodeDistance2[pts[i]];
-          MESSAGE("point " << pts[i] << " distance2 " << distance2);
+          //MESSAGE("point " << pts[i] << " distance2 " << distance2);
         }
         else
         {
@@ -12058,7 +12152,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
             }
           }
           mapOfNodeDistance2[pts[i]] = distance2;
-          MESSAGE("  point "  << pts[i]  << " distance2 " << distance2 << " coords " << coords[0] << " " << coords[1] << " " <<  coords[2]);
+          //MESSAGE("  point "  << pts[i]  << " distance2 " << distance2 << " coords " << coords[0] << " " << coords[1] << " " <<  coords[2]);
         }
         if (distance2 < radius2)
         {
@@ -12070,7 +12164,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       if (volInside)
       {
         setOfInsideVol.insert(vtkId);
-        MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
         unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12082,7 +12176,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       else
       {
         setOfOutsideVol.insert(vtkId);
-        MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
       }
       setOfVolToCheck.erase(vtkId);
     }
@@ -12095,7 +12189,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   std::set<int> setOfVolToReCheck;
   while (addedInside)
   {
-    MESSAGE(" --------------------------- re check");
+    //MESSAGE(" --------------------------- re check");
     addedInside = false;
     std::set<int>::iterator itv = setOfInsideVol.begin();
     for (; itv != setOfInsideVol.end(); ++itv)
@@ -12117,7 +12211,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       int vtkId = *it;
       if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON)
       {
-        MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
         int countInside = 0;
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
@@ -12126,10 +12220,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         for (int n = 0; n < nbNeighbors; n++)
           if (setOfInsideVol.count(neighborsVtkIds[n]))
             countInside++;
-        MESSAGE("countInside " << countInside);
+        //MESSAGE("countInside " << countInside);
         if (countInside > 1)
         {
-          MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+          //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
           setOfInsideVol.insert(vtkId);
           sgrp->Add(meshDS->fromVtkToSmds(vtkId));
           addedInside = true;
@@ -12226,7 +12320,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   for (; itShape != shapeIdToVtkIdSet.end(); ++itShape)
   {
     int shapeId = itShape->first;
-    MESSAGE(" --- Shape ID --- "<< shapeId);
+    //MESSAGE(" --- Shape ID --- "<< shapeId);
     shapeIdToEdges[shapeId] = emptyEdges;
 
     std::vector<int> nodesEdges;
@@ -12235,7 +12329,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     for (; its != itShape->second.end(); ++its)
     {
       int vtkId = *its;
-      MESSAGE("     " << vtkId);
+      //MESSAGE("     " << vtkId);
       int neighborsVtkIds[NBMAXNEIGHBORS];
       int downIds[NBMAXNEIGHBORS];
       unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12256,7 +12350,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
             int nbNodes = grid->getDownArray(downTypes[n])->getNodes(downIds[n],vtkNodeId);
             nodesEdges.push_back(vtkNodeId[0]);
             nodesEdges.push_back(vtkNodeId[nbNodes-1]);
-            MESSAGE("       --- nodes " << vtkNodeId[0]+1 << " " << vtkNodeId[nbNodes-1]+1);
+            //MESSAGE("       --- nodes " << vtkNodeId[0]+1 << " " << vtkNodeId[nbNodes-1]+1);
           }
         }
       }
@@ -12266,9 +12360,9 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     order.clear();
     if (nodesEdges.size() > 0)
     {
-      order.push_back(nodesEdges[0]); MESSAGE("       --- back " << order.back()+1); // SMDS id = VTK id + 1;
+      order.push_back(nodesEdges[0]); //MESSAGE("       --- back " << order.back()+1); // SMDS id = VTK id + 1;
       nodesEdges[0] = -1;
-      order.push_back(nodesEdges[1]); MESSAGE("       --- back " << order.back()+1);
+      order.push_back(nodesEdges[1]); //MESSAGE("       --- back " << order.back()+1);
       nodesEdges[1] = -1; // do not reuse this edge
       bool found = true;
       while (found)
@@ -12287,7 +12381,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
               found = false;
             else
             {
-              order.push_back(nodesEdges[i-1]); MESSAGE("       --- back " << order.back()+1);
+              order.push_back(nodesEdges[i-1]); //MESSAGE("       --- back " << order.back()+1);
               nodesEdges[i-1] = -1;
             }
           else // even ==> use the next one
@@ -12295,7 +12389,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
               found = false;
             else
             {
-              order.push_back(nodesEdges[i+1]); MESSAGE("       --- back " << order.back()+1);
+              order.push_back(nodesEdges[i+1]); //MESSAGE("       --- back " << order.back()+1);
               nodesEdges[i+1] = -1;
             }
         }
@@ -12317,7 +12411,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
             found = false;
           else
           {
-            order.push_front(nodesEdges[i-1]); MESSAGE("       --- front " << order.front()+1);
+            order.push_front(nodesEdges[i-1]); //MESSAGE("       --- front " << order.front()+1);
             nodesEdges[i-1] = -1;
           }
         else // even ==> use the next one
@@ -12325,7 +12419,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
             found = false;
           else
           {
-            order.push_front(nodesEdges[i+1]); MESSAGE("       --- front " << order.front()+1);
+            order.push_front(nodesEdges[i+1]); //MESSAGE("       --- front " << order.front()+1);
             nodesEdges[i+1] = -1;
           }
       }
@@ -12338,7 +12432,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     for (; itl != order.end(); itl++)
     {
       nodes.push_back((*itl) + 1); // SMDS id = VTK id + 1;
-      MESSAGE("              ordered node " << nodes[nodes.size()-1]);
+      //MESSAGE("              ordered node " << nodes[nodes.size()-1]);
     }
     listOfListOfNodes.push_back(nodes);
   }
@@ -12740,3 +12834,448 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   default:;
   }
 }
+
+namespace // utils for MakePolyLine
+{
+  //================================================================================
+  /*!
+   * \brief Sequence of found points and a current point data
+   */
+  struct Path
+  {
+    std::vector< gp_XYZ >   myPoints;
+    double                  myLength;
+
+    int                     mySrcPntInd; //!< start point index
+    const SMDS_MeshElement* myFace;
+    SMESH_NodeXYZ           myNode1;
+    SMESH_NodeXYZ           myNode2;
+    int                     myNodeInd1;
+    int                     myNodeInd2;
+    double                  myDot1;
+    double                  myDot2;
+    TIDSortedElemSet        myElemSet, myAvoidSet;
+
+    Path(): myLength(0.0), myFace(0) {}
+
+    bool SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                         const SMDS_MeshElement* face,
+                         const gp_XYZ&           plnNorm,
+                         const gp_XYZ&           plnOrig );
+
+    void AddPoint( const gp_XYZ& p );
+
+    bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig );
+
+    static void Remove( std::vector< Path > & paths, size_t& i );
+  };
+
+  //================================================================================
+  /*!
+   * \brief Remove a path from a vector
+   */
+  //================================================================================
+
+  void Path::Remove( std::vector< Path > & paths, size_t& i )
+  {
+    size_t j = paths.size() - 1; // last item to be removed
+    if ( i < j )
+    {
+      paths[ i ].myPoints.swap( paths[ j ].myPoints );
+      paths[ i ].myFace     = paths[ j ].myFace;
+      paths[ i ].myNodeInd1 = paths[ j ].myNodeInd1;
+      paths[ i ].myNodeInd2 = paths[ j ].myNodeInd2;
+      paths[ i ].myNode1    = paths[ j ].myNode1;
+      paths[ i ].myNode2    = paths[ j ].myNode2;
+      paths[ i ].myLength   = paths[ j ].myLength;
+    }
+    paths.pop_back();
+    --i;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point that is at a node of a face if the face is intersected by plane.
+   *        Return false if the node is a sole intersection point of the face and the plane
+   */
+  //================================================================================
+
+  bool Path::SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                             const SMDS_MeshElement* face,
+                             const gp_XYZ&           plnNorm,
+                             const gp_XYZ&           plnOrig )
+  {
+    if ( face == myFace )
+      return false;
+    myNodeInd1 = face->GetNodeIndex( cornerNode._node );
+    myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes();
+    int   ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes();
+    myNode1.Set( face->GetNode( ind3 ));
+    myNode2.Set( face->GetNode( myNodeInd2 ));
+
+    myDot1 = plnNorm * ( myNode1 - plnOrig );
+    myDot2 = plnNorm * ( myNode2 - plnOrig );
+
+    bool ok = ( myDot1 * myDot2 < 0 );
+    if ( !ok && myDot1 * myDot2 == 0 )
+    {
+      ok = ( myDot1 != myDot2 );
+      if ( ok && myFace )
+        ok = ( myFace->GetNodeIndex( myNode1._node ) < 0 &&
+               myFace->GetNodeIndex( myNode2._node ) < 0 );
+    }
+    if ( ok )
+    {
+      myFace = face;
+      myDot1 = 0;
+      AddPoint( cornerNode );
+    }
+    return ok;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point and update myLength
+   */
+  //================================================================================
+
+  void Path::AddPoint( const gp_XYZ& p )
+  {
+    if ( !myPoints.empty() )
+      myLength += ( p - myPoints.back() ).Modulus();
+    else
+      myLength = 0;
+    myPoints.push_back( p );
+  }
+
+  //================================================================================
+  /*!
+   * \brief Try to find the next point
+   *  \param [in] plnNorm - cutting plane normal
+   *  \param [in] plnOrig - cutting plane origin
+   */
+  //================================================================================
+
+  bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig )
+  {
+    int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes();
+    if ( myNodeInd2 == nodeInd3 )
+      nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes();
+
+    SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 );
+    double         dot3 = plnNorm * ( node3 - plnOrig );
+
+    if ( dot3 * myDot1 < 0. )
+    {
+      myNode2    = node3;
+      myNodeInd2 = nodeInd3;
+      myDot2     = dot3;
+    }
+    else if ( dot3 * myDot2 < 0. )
+    {
+      myNode1    = node3;
+      myNodeInd1 = nodeInd3;
+      myDot1     = dot3;
+    }
+    else if ( dot3 == 0. )
+    {
+      SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+    else if ( myDot2 == 0. )
+    {
+      SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner()
+      SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+
+    double r = Abs( myDot1 / ( myDot2 - myDot1 ));
+    AddPoint( myNode1 * ( 1 - r ) + myNode2 * r );
+
+    myAvoidSet.clear();
+    myAvoidSet.insert( myFace );
+    myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node,
+                                             myElemSet,   myAvoidSet,
+                                             &myNodeInd1, &myNodeInd2 );
+    return myFace;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Compute a path between two points of PolySegment
+   */
+  struct PolyPathCompute
+  {
+    SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's
+    std::vector< Path >&                   myPaths;    //!< path of each of segments to compute
+    SMESH_Mesh*                            myMesh;
+    mutable std::vector< std::string >     myErrors;
+
+    PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments,
+                     std::vector< Path >&                   thePaths,
+                     SMESH_Mesh*                            theMesh):
+      mySegments( theSegments ),
+      myPaths( thePaths ),
+      myMesh( theMesh ),
+      myErrors( theSegments.size() )
+    {
+    }
+#undef SMESH_CAUGHT
+#define SMESH_CAUGHT myErrors[i] =
+    void operator() ( const int i ) const
+    {
+      SMESH_TRY;
+      const_cast< PolyPathCompute* >( this )->Compute( i );
+      SMESH_CATCH( SMESH::returnError );
+    }
+#undef SMESH_CAUGHT
+    //================================================================================
+    /*!
+     * \brief Compute a path of a given segment
+     */
+    //================================================================================
+
+    void Compute( const int iSeg )
+    {
+      SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
+
+      // get a cutting plane
+
+      gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+      gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+      if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+      if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+      gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+      gp_XYZ plnOrig = SMESH_NodeXYZ( polySeg.myNode1[0] );
+
+      // find paths connecting the 2 end points of polySeg
+
+      std::vector< Path > paths; paths.reserve(10);
+
+      // initialize paths
+
+      for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
+      {
+        Path path;
+        path.mySrcPntInd = iP;
+        size_t nbPaths = paths.size();
+
+        if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
+        {
+          while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
+                                                                 polySeg.myNode2[ iP ],
+                                                                 path.myElemSet,
+                                                                 path.myAvoidSet,
+                                                                 &path.myNodeInd1,
+                                                                 &path.myNodeInd2 )))
+          {
+            path.myNode1.Set( polySeg.myNode1[ iP ]);
+            path.myNode2.Set( polySeg.myNode2[ iP ]);
+            path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
+            path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
+            path.myPoints.clear();
+            path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
+            path.myAvoidSet.insert( path.myFace );
+            paths.push_back( path );
+          }
+          if ( nbPaths == paths.size() )
+            throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
+                                     << " in a PolySegment " << iSeg );
+        }
+        else // an end point is at node
+        {
+          std::set<const SMDS_MeshNode* > nodes;
+          SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
+          while ( fIt->more() )
+          {
+            path.myPoints.clear();
+            if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig ))
+            {
+              if (( path.myDot1 * path.myDot2 != 0 ) ||
+                  ( nodes.insert( path.myNode1._node ).second &&
+                    nodes.insert( path.myNode2._node ).second ))
+                paths.push_back( path );
+            }
+          }
+        }
+
+        // look for a one-segment path
+        for ( size_t i = 0; i < nbPaths; ++i )
+          for ( size_t j = nbPaths; j < paths.size(); ++j )
+            if ( paths[i].myFace == paths[j].myFace )
+            {
+              myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] );
+              myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] );
+              paths.clear();
+            }
+      }
+
+      // extend paths
+
+      myPaths[ iSeg ].myLength = 1e100;
+
+      while ( paths.size() >= 2 )
+      {
+        for ( size_t i = 0; i < paths.size(); ++i )
+        {
+          Path& path = paths[ i ];
+          if ( !path.Extend( plnNorm, plnOrig ) ||         // path reached a mesh boundary
+               path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
+          {
+            Path::Remove( paths, i );
+            continue;
+          }
+
+          // join paths that reach same point
+          for ( size_t j = 0; j < paths.size(); ++j )
+          {
+            if ( i != j &&
+                 paths[i].myFace == paths[j].myFace &&
+                 paths[i].mySrcPntInd != paths[j].mySrcPntInd )
+            {
+              double   distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus();
+              double fullLength = ( paths[i].myLength + paths[j].myLength + distLast );
+              if ( fullLength < myPaths[ iSeg ].myLength )
+              {
+                myPaths[ iSeg ].myLength = fullLength;
+                std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints;
+                allPoints.swap( paths[i].myPoints );
+                allPoints.insert( allPoints.end(),
+                                  paths[j].myPoints.rbegin(),
+                                  paths[j].myPoints.rend() );
+              }
+              Path::Remove( paths, i );
+              Path::Remove( paths, j );
+            }
+          }
+        }
+        if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() )
+          throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()"));
+      }
+
+      return;
+
+    } // PolyPathCompute::Compute()
+
+  }; // struct PolyPathCompute
+
+} // namespace
+
+//=======================================================================
+//function : MakePolyLine
+//purpose  : Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+//           the initial mesh
+//=======================================================================
+
+void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments&   theSegments,
+                                     SMESHDS_Group*         theGroup,
+                                     SMESH_ElementSearcher* theSearcher)
+{
+  std::vector< Path > segPaths( theSegments.size() ); // path of each of segments
+
+  SMESH_ElementSearcher* searcher = theSearcher;
+  SMESHUtils::Deleter<SMESH_ElementSearcher> delSearcher;
+  if ( !searcher )
+  {
+    searcher = SMESH_MeshAlgos::GetElementSearcher( *myMesh->GetMeshDS() );
+    delSearcher._obj = searcher;
+  }
+
+  // get cutting planes
+
+  std::vector< bool > isVectorOK( theSegments.size(), true );
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    PolySegment& polySeg = theSegments[ iSeg ];
+
+    gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+    gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+    if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+    if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+    gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+
+    isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
+    if ( !isVectorOK[ iSeg ])
+    {
+      gp_XYZ pMid = 0.5 * ( p1 + p2 );
+      const SMDS_MeshElement* face;
+      polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face );
+
+      if ( polySeg.myMidProjPoint.Distance( pMid ) < Precision::Confusion() )
+      {
+        SMESH_MeshAlgos::FaceNormal( face, const_cast< gp_XYZ& >( polySeg.myVector.XYZ() ));
+        polySeg.myMidProjPoint = pMid + polySeg.myVector.XYZ();
+      }
+    }
+  }
+
+  // find paths
+
+  PolyPathCompute algo( theSegments, segPaths, myMesh );
+  OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 );
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+    if ( !algo.myErrors[ iSeg ].empty() )
+      throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() );
+
+  // create an 1D mesh
+
+  const SMDS_MeshNode *n, *nPrev = 0;
+  SMESHDS_Mesh* mesh = GetMeshDS();
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    const Path& path = segPaths[iSeg];
+    if ( path.myPoints.size() < 2 )
+      continue;
+
+    double tol = path.myLength / path.myPoints.size() / 1000.;
+    if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol )
+    {
+      nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() );
+      myLastCreatedNodes.Append( nPrev );
+    }
+    for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+    {
+      n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
+      myLastCreatedNodes.Append( n );
+
+      const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
+      myLastCreatedElems.Append( elem );
+      if ( theGroup )
+        theGroup->Add( elem );
+
+      nPrev = n;
+    }
+
+    // return a vector
+
+    if ( isVectorOK[ iSeg ])
+    {
+      // find the most distance point of a path
+      double maxDist = 0;
+      for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+      {
+        double dist = theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] );
+        if ( dist > maxDist )
+        {
+          maxDist = dist;
+          theSegments[iSeg].myMidProjPoint = path.myPoints[iP];
+        }
+      }
+    }
+    gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() );
+    theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint );
+  }
+
+  return;
+}
index 103e4a4172ca4b0028106ccea29044ed35d6b3bd..a04f8dac1cef5987d415000cd3ca7c098a946433 100644 (file)
 class SMDS_MeshElement;
 class SMDS_MeshFace;
 class SMDS_MeshNode;
+class SMESHDS_Group;
 class SMESHDS_Mesh;
 class SMESHDS_SubMesh;
+class SMESH_ElementSearcher;
 class SMESH_Group;
 class SMESH_Mesh;
 class SMESH_MesherHelper;
@@ -83,11 +85,12 @@ public:
   // --------------------------------------------------------------------------------
   struct ElemFeatures //!< Features of element to create
   {
-    SMDSAbs_ElementType myType;
-    bool                myIsPoly, myIsQuad;
-    int                 myID;
-    double              myBallDiameter;
-    std::vector<int>    myPolyhedQuantities;
+    SMDSAbs_ElementType               myType;
+    bool                              myIsPoly, myIsQuad;
+    int                               myID;
+    double                            myBallDiameter;
+    std::vector<int>                  myPolyhedQuantities;
+    std::vector<const SMDS_MeshNode*> myNodes; // not managed by ElemFeatures
 
     SMESH_EXPORT ElemFeatures( SMDSAbs_ElementType type=SMDSAbs_All, bool isPoly=false, bool isQuad=false )
       :myType( type ), myIsPoly(isPoly), myIsQuad(isQuad), myID(-1), myBallDiameter(0) {}
@@ -471,7 +474,8 @@ public:
   // Return list of group of nodes close to each other within theTolerance.
   // Search among theNodes or in the whole mesh if theNodes is empty.
 
-  void MergeNodes (TListOfListOfNodes & theNodeGroups);
+  void MergeNodes (TListOfListOfNodes & theNodeGroups,
+                   const bool           theAvoidMakingHoles = false);
   // In each group, the cdr of nodes are substituted by the first one
   // in all elements.
 
@@ -540,7 +544,7 @@ public:
   // additional nodes are inserted on a link provided that no
   // volume elements share the splitted link.
   // The side 2 is a free border if theSide2IsFreeBorder == true.
-  // Sewing is peformed between the given first, second and last
+  // Sewing is performed between the given first, second and last
   // nodes on the sides.
   // theBorderFirstNode is merged with theSide2FirstNode.
   // if (!theSide2IsFreeBorder) then theSide2SecondNode gives
@@ -705,6 +709,42 @@ public:
                        bool                    toAddExistingBondary = false,
                        bool                    aroundElements = false);
 
+
+  // structure used in MakePolyLine() to define a cutting plane
+  struct PolySegment
+  {
+    // 2 points: if myNode2 != 0, then the point is the middle of a face edge defined
+    //           by two nodes, else it is at myNode1
+    const SMDS_MeshNode* myNode1[2];
+    const SMDS_MeshNode* myNode2[2];
+
+    gp_Vec myVector; // vector on the plane; to use a default plane set vector = (0,0,0)
+
+    // point to return coordinates of a middle of the two points, projected to mesh
+    gp_Pnt myMidProjPoint;
+  };
+  typedef std::vector<PolySegment> TListOfPolySegments;
+
+  /*!
+   * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+   *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+   *        plane passing through pairs of points specified by each PolySegment structure.
+   *        If there are several paths connecting a pair of points, the shortest path is
+   *        selected by the module. Position of the cutting plane is defined by the two
+   *        points and an optional vector lying on the plane specified by a PolySegment.
+   *        By default the vector is defined by Mesh module as following. A middle point
+   *        of the two given points is computed. The middle point is projected to the mesh.
+   *        The vector goes from the middle point to the projection point. In case of planar
+   *        mesh, the vector is normal to the mesh.
+   *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+   *        Return the used vector and position of the middle point.
+   *  \param [in] group - an optional group where created mesh segments will
+   *        be added.
+   */
+  void MakePolyLine( TListOfPolySegments&   segments,
+                     SMESHDS_Group*         group=0,
+                     SMESH_ElementSearcher* searcher=0);
+
  private:
 
   /*!
@@ -749,6 +789,20 @@ public:
                     const size_t                               nbSteps,
                     SMESH_SequenceOfElemPtr&                   srcElements);
 
+  /*!
+   * \brief Computes new connectivity of an element after merging nodes
+   *  \param [in] elems - the element
+   *  \param [out] newElemDefs - definition(s) of result element(s)
+   *  \param [inout] nodeNodeMap - nodes to merge
+   *  \param [in] avoidMakingHoles - if true and and the element becomes invalid
+   *             after merging (but not degenerated), removes nodes causing
+   *             the invalidity from \a nodeNodeMap.
+   *  \return bool - true if the element should be removed
+   */
+  bool applyMerge( const SMDS_MeshElement*      elems,
+                   std::vector< ElemFeatures >& newElemDefs,
+                   TNodeNodeMap&                nodeNodeMap,
+                   const bool                   avoidMakingHoles );
   /*!
    * \brief Create 1D and 2D elements around swept elements
    * \param mapNewNodes - source nodes and ones generated from them
@@ -781,11 +835,11 @@ public:
     double        Angle       ()const               { return myAngle; }
     double        Parameter   ()const               { return myPrm; }
   };
-  Extrusion_Error MakeEdgePathPoints(std::list<double>&                     aPrms,
+  Extrusion_Error makeEdgePathPoints(std::list<double>&                     aPrms,
                                      const TopoDS_Edge&                     aTrackEdge,
                                      bool                                   aFirstIsStart,
                                      std::list<SMESH_MeshEditor_PathPoint>& aLPP);
-  Extrusion_Error MakeExtrElements(TIDSortedElemSet                       theElements[2],
+  Extrusion_Error makeExtrElements(TIDSortedElemSet                       theElements[2],
                                    std::list<SMESH_MeshEditor_PathPoint>& theFullList,
                                    const bool                             theHasAngles,
                                    std::list<double>&                     theAngles,
@@ -793,7 +847,7 @@ public:
                                    const bool                             theHasRefPoint,
                                    const gp_Pnt&                          theRefPoint,
                                    const bool                             theMakeGroups);
-  static void LinearAngleVariation(const int          NbSteps,
+  static void linearAngleVariation(const int          NbSteps,
                                    std::list<double>& theAngles);
 
   bool doubleNodes( SMESHDS_Mesh*           theMeshDS,
@@ -812,7 +866,7 @@ private:
   // Nodes and elements created during last operation
   SMESH_SequenceOfElemPtr myLastCreatedNodes, myLastCreatedElems;
 
-  // Description of error/warning occured during last operation
+  // Description of error/warning occurred during last operation
   SMESH_ComputeErrorPtr   myError;
 };
 
index e5dcf5d12652d2c30cedecc2a71f252ebe94d4f5..2aba558af7aa5b6a827d67a863e8545462c1a3cf 100644 (file)
@@ -191,6 +191,9 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
     SeparateCornersAndMedium = new QCheckBox(tr("SEPARATE_CORNERS_AND_MEDIUM"), NodeSpecWidget );
     SeparateCornersAndMedium->setEnabled( false );
 
+    AvoidMakingHoles = new QCheckBox(tr("AVOID_MAKING_HOLES"), NodeSpecWidget );
+    AvoidMakingHoles->setChecked( false );
+
     QGridLayout* NodeSpecLayout = new QGridLayout(NodeSpecWidget);
     NodeSpecLayout->setSpacing(SPACING);
     NodeSpecLayout->setMargin(0);
@@ -198,6 +201,7 @@ SMESHGUI_MergeDlg::SMESHGUI_MergeDlg (SMESHGUI* theModule, int theAction)
     NodeSpecLayout->addWidget(TextLabelTolerance,       0, 0 );
     NodeSpecLayout->addWidget(SpinBoxTolerance,         0, 1 );
     NodeSpecLayout->addWidget(SeparateCornersAndMedium, 1, 0, 1, 2 );
+    NodeSpecLayout->addWidget(AvoidMakingHoles,         2, 0, 1, 2 );
 
     /***************************************************************/
     // Exclude groups
@@ -585,12 +589,12 @@ bool SMESHGUI_MergeDlg::ClickOnApply()
     }
 
     if( myAction == MERGE_NODES )
-      aMeshEditor->MergeNodes (aGroupsOfElements.inout(), nodesToKeep);
+      aMeshEditor->MergeNodes( aGroupsOfElements.inout(), nodesToKeep, AvoidMakingHoles->isChecked() );
     else
-      aMeshEditor->MergeElements (aGroupsOfElements.inout());
+      aMeshEditor->MergeElements( aGroupsOfElements.inout() );
 
     if ( myTypeId == TYPE_AUTO ) {
-      if (myAction == MERGE_NODES )
+      if ( myAction == MERGE_NODES )
         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
                                      tr("SMESH_MERGED_NODES").arg(QString::number(ListCoincident->count()).toLatin1().data()));
       else
index 5e827abc84198e250aca314d5d6614c615cdc3ef..6b087b631c41d110ce318bdf9ceee8a7dbe2fba6 100644 (file)
@@ -130,6 +130,7 @@ private:
   QWidget*                  NodeSpecWidget;
   SMESHGUI_SpinBox*         SpinBoxTolerance;
   QCheckBox*                SeparateCornersAndMedium;
+  QCheckBox*                AvoidMakingHoles;
 
   QGroupBox*                GroupCoincident;
   //QWidget*                  GroupCoincidentWidget;
index 6670e509e9d00a8d06677dd91ee726145a6a8902..8e03e4e679e6ecdd6bf67c4f0366e01f59e34e3e 100644 (file)
@@ -35,6 +35,8 @@
 #include "SMDS_VolumeTool.hxx"
 #include "SMESH_OctreeNode.hxx"
 
+#include <Utils_SALOME_Exception.hxx>
+
 #include <GC_MakeSegment.hxx>
 #include <GeomAPI_ExtremaCurveCurve.hxx>
 #include <Geom_Line.hxx>
@@ -228,15 +230,16 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
                       SMDSAbs_ElementType  elemType,
                       SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(),
                       double               tolerance = NodeRadius );
-    void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems );
-    void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems);
-    void getElementsInSphere ( const gp_XYZ& center,
-                               const double  radius, TIDSortedElemSet& foundElems);
-    size_t getSize() { return std::max( _size, _elements.size() ); }
-    virtual ~ElementBndBoxTree();
+    void prepare(); // !!!call it before calling the following methods!!!
+    void getElementsNearPoint( const gp_Pnt& point, vector<const SMDS_MeshElement*>& foundElems );
+    void getElementsNearLine ( const gp_Ax1& line,  vector<const SMDS_MeshElement*>& foundElems);
+    void getElementsInSphere ( const gp_XYZ&                    center,
+                               const double                     radius,
+                               vector<const SMDS_MeshElement*>& foundElems);
+    ElementBndBoxTree* getLeafAtPoint( const gp_XYZ& point );
 
   protected:
-    ElementBndBoxTree():_size(0) {}
+    ElementBndBoxTree() {}
     SMESH_Octree* newChild() const { return new ElementBndBoxTree; }
     void          buildChildrenData();
     Bnd_B3d*      buildRootBox();
@@ -245,11 +248,25 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
     struct ElementBox : public Bnd_B3d
     {
       const SMDS_MeshElement* _element;
-      int                     _refCount; // an ElementBox can be included in several tree branches
-      ElementBox(const SMDS_MeshElement* elem, double tolerance);
+      bool                    _isMarked;
+      void init(const SMDS_MeshElement* elem, double tolerance);
     };
     vector< ElementBox* > _elements;
-    size_t                _size;
+
+    typedef ObjectPool< ElementBox > TElementBoxPool;
+
+    //!< allocator of ElementBox's and SMESH_TreeLimit
+    struct LimitAndPool : public SMESH_TreeLimit
+    {
+      TElementBoxPool            _elBoPool;
+      std::vector< ElementBox* > _markedElems;
+      LimitAndPool():SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ) {}
+    };
+    LimitAndPool* getLimitAndPool() const
+    {
+      SMESH_TreeLimit* limitAndPool = const_cast< SMESH_TreeLimit* >( myLimit );
+      return static_cast< LimitAndPool* >( limitAndPool );
+    }
   };
 
   //================================================================================
@@ -258,32 +275,27 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance)
-    :SMESH_Octree( new SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ))
+  ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh&     mesh,
+                                       SMDSAbs_ElementType  elemType,
+                                       SMDS_ElemIteratorPtr theElemIt,
+                                       double               tolerance)
+    :SMESH_Octree( new LimitAndPool() )
   {
     int nbElems = mesh.GetMeshInfo().NbElements( elemType );
     _elements.reserve( nbElems );
 
+    TElementBoxPool& elBoPool = getLimitAndPool()->_elBoPool;
+
     SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType );
     while ( elemIt->more() )
-      _elements.push_back( new ElementBox( elemIt->next(),tolerance  ));
-
+    {
+      ElementBox* eb = elBoPool.getNew();
+      eb->init( elemIt->next(), tolerance );
+      _elements.push_back( eb );
+    }
     compute();
   }
 
-  //================================================================================
-  /*!
-   * \brief Destructor
-   */
-  //================================================================================
-
-  ElementBndBoxTree::~ElementBndBoxTree()
-  {
-    for ( size_t i = 0; i < _elements.size(); ++i )
-      if ( --_elements[i]->_refCount <= 0 )
-        delete _elements[i];
-  }
-
   //================================================================================
   /*!
    * \brief Return the maximal box
@@ -311,14 +323,10 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
       for (int j = 0; j < 8; j++)
       {
         if ( !_elements[i]->IsOut( *myChildren[j]->getBox() ))
-        {
-          _elements[i]->_refCount++;
           ((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
-        }
       }
-      _elements[i]->_refCount--;
     }
-    _size = _elements.size();
+    //_size = _elements.size();
     SMESHUtils::FreeVector( _elements ); // = _elements.clear() + free memory
 
     for (int j = 0; j < 8; j++)
@@ -327,33 +335,61 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
       if ((int) child->_elements.size() <= MaxNbElemsInLeaf )
         child->myIsLeaf = true;
 
-      if ( child->_elements.capacity() - child->_elements.size() > 1000 )
+      if ( child->isLeaf() && child->_elements.capacity() > child->_elements.size() )
         SMESHUtils::CompactVector( child->_elements );
     }
   }
 
+  //================================================================================
+  /*!
+   * \brief Un-mark all elements
+   */
+  //================================================================================
+
+  void ElementBndBoxTree::prepare()
+  {
+    // TElementBoxPool& elBoPool = getElementBoxPool();
+    // for ( size_t i = 0; i < elBoPool.nbElements(); ++i )
+    //   const_cast< ElementBox* >( elBoPool[ i ])->_isMarked = false;
+  }
+
   //================================================================================
   /*!
    * \brief Return elements which can include the point
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt&     point,
-                                                TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt&                    point,
+                                                vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( point.XYZ() ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( point.XYZ() ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( point.XYZ() ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
     }
   }
 
@@ -363,22 +399,37 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsNearLine( const gp_Ax1&     line,
-                                               TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsNearLine( const gp_Ax1&                    line,
+                                               vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( line ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( line ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( line ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
     }
   }
 
@@ -388,24 +439,63 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ&     center,
-                                                const double      radius,
-                                                TIDSortedElemSet& foundElems)
+  void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ&                    center,
+                                                const double                     radius,
+                                                vector<const SMDS_MeshElement*>& foundElems)
   {
     if ( getBox()->IsOut( center, radius ))
       return;
 
     if ( isLeaf() )
     {
+      LimitAndPool* pool = getLimitAndPool();
+
       for ( size_t i = 0; i < _elements.size(); ++i )
-        if ( !_elements[i]->IsOut( center, radius ))
-          foundElems.insert( _elements[i]->_element );
+        if ( !_elements[i]->IsOut( center, radius ) &&
+             !_elements[i]->_isMarked )
+        {
+          foundElems.push_back( _elements[i]->_element );
+          _elements[i]->_isMarked = true;
+          pool->_markedElems.push_back( _elements[i] );
+        }
     }
     else
     {
       for (int i = 0; i < 8; i++)
         ((ElementBndBoxTree*) myChildren[i])->getElementsInSphere( center, radius, foundElems );
+
+      if ( level() == 0 )
+      {
+        LimitAndPool* pool = getLimitAndPool();
+        for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
+          pool->_markedElems[i]->_isMarked = false;
+        pool->_markedElems.clear();
+      }
+    }
+  }
+
+  //================================================================================
+  /*!
+   * \brief Return a leaf including a point
+   */
+  //================================================================================
+
+  ElementBndBoxTree* ElementBndBoxTree::getLeafAtPoint( const gp_XYZ& point )
+  {
+    if ( getBox()->IsOut( point ))
+      return 0;
+
+    if ( isLeaf() )
+    {
+      return this;
+    }
+    else
+    {
+      for (int i = 0; i < 8; i++)
+        if ( ElementBndBoxTree* l = ((ElementBndBoxTree*) myChildren[i])->getLeafAtPoint( point ))
+          return l;
     }
+    return 0;
   }
 
   //================================================================================
@@ -414,13 +504,13 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
    */
   //================================================================================
 
-  ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance)
+  void ElementBndBoxTree::ElementBox::init(const SMDS_MeshElement* elem, double tolerance)
   {
     _element  = elem;
-    _refCount = 1;
+    _isMarked = false;
     SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
     while ( nIt->more() )
-      Add( SMESH_TNodeXYZ( nIt->next() ));
+      Add( SMESH_NodeXYZ( nIt->next() ));
     Enlarge( tolerance );
   }
 
@@ -441,8 +531,8 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
 {
   SMDS_Mesh*                   _mesh;
   SMDS_ElemIteratorPtr         _meshPartIt;
-  ElementBndBoxTree*           _ebbTree;
-  int                          _ebbTreeHeight;
+  ElementBndBoxTree*           _ebbTree      [SMDSAbs_NbElementTypes];
+  int                          _ebbTreeHeight[SMDSAbs_NbElementTypes];
   SMESH_NodeSearcherImpl*      _nodeSearcher;
   SMDSAbs_ElementType          _elementType;
   double                       _tolerance;
@@ -452,10 +542,21 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
   SMESH_ElementSearcherImpl( SMDS_Mesh&           mesh,
                              double               tol=-1,
                              SMDS_ElemIteratorPtr elemIt=SMDS_ElemIteratorPtr())
-    : _mesh(&mesh),_meshPartIt(elemIt),_ebbTree(0),_ebbTreeHeight(-1),_nodeSearcher(0),_tolerance(tol),_outerFacesFound(false) {}
+    : _mesh(&mesh),_meshPartIt(elemIt),_nodeSearcher(0),_tolerance(tol),_outerFacesFound(false)
+  {
+    for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
+    {
+      _ebbTree[i] = NULL;
+      _ebbTreeHeight[i] = -1;
+    }
+    _elementType = SMDSAbs_All;
+  }
   virtual ~SMESH_ElementSearcherImpl()
   {
-    if ( _ebbTree )      delete _ebbTree;      _ebbTree      = 0;
+    for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
+    {
+      delete _ebbTree[i]; _ebbTree[i] = NULL;
+    }
     if ( _nodeSearcher ) delete _nodeSearcher; _nodeSearcher = 0;
   }
   virtual int FindElementsByPoint(const gp_Pnt&                      point,
@@ -465,13 +566,16 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
   virtual const SMDS_MeshElement* FindClosestTo( const gp_Pnt&       point,
                                                  SMDSAbs_ElementType type );
 
-  void GetElementsNearLine( const gp_Ax1&                      line,
-                            SMDSAbs_ElementType                type,
-                            vector< const SMDS_MeshElement* >& foundElems);
-  void GetElementsInSphere( const gp_XYZ&                      center,
-                            const double                       radius,
-                            SMDSAbs_ElementType                type,
-                            vector< const SMDS_MeshElement* >& foundElems);
+  virtual void GetElementsNearLine( const gp_Ax1&                      line,
+                                    SMDSAbs_ElementType                type,
+                                    vector< const SMDS_MeshElement* >& foundElems);
+  virtual void GetElementsInSphere( const gp_XYZ&                      center,
+                                    const double                       radius,
+                                    SMDSAbs_ElementType                type,
+                                    vector< const SMDS_MeshElement* >& foundElems);
+  virtual gp_XYZ Project(const gp_Pnt&            point,
+                         SMDSAbs_ElementType      type,
+                         const SMDS_MeshElement** closestElem);
   double getTolerance();
   bool getIntersParamOnLine(const gp_Lin& line, const SMDS_MeshElement* face,
                             const double tolerance, double & param);
@@ -482,9 +586,9 @@ struct SMESH_ElementSearcherImpl: public SMESH_ElementSearcher
   }
   int getTreeHeight()
   {
-    if ( _ebbTreeHeight < 0 )
-      _ebbTreeHeight = _ebbTree->getHeight();
-    return _ebbTreeHeight;
+    if ( _ebbTreeHeight[ _elementType ] < 0 )
+      _ebbTreeHeight[ _elementType ] = _ebbTree[ _elementType ]->getHeight();
+    return _ebbTreeHeight[ _elementType ];
   }
 
   struct TInters //!< data of intersection of the line and the mesh face (used in GetPointState())
@@ -528,9 +632,9 @@ double SMESH_ElementSearcherImpl::getTolerance()
       double boxSize = _nodeSearcher->getTree()->maxSize();
       _tolerance = 1e-8 * boxSize/* / meshInfo.NbNodes()*/;
     }
-    else if ( _ebbTree && meshInfo.NbElements() > 0 )
+    else if ( _ebbTree[_elementType] && meshInfo.NbElements() > 0 )
     {
-      double boxSize = _ebbTree->maxSize();
+      double boxSize = _ebbTree[_elementType]->maxSize();
       _tolerance = 1e-8 * boxSize/* / meshInfo.NbElements()*/;
     }
     if ( _tolerance == 0 )
@@ -551,10 +655,9 @@ double SMESH_ElementSearcherImpl::getTolerance()
       }
       else
       {
-        SMDS_ElemIteratorPtr elemIt =
-            _mesh->elementsIterator( SMDSAbs_ElementType( complexType ));
+        SMDS_ElemIteratorPtr  elemIt = _mesh->elementsIterator( SMDSAbs_ElementType( complexType ));
         const SMDS_MeshElement* elem = elemIt->next();
-        SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+        SMDS_ElemIteratorPtr  nodeIt = elem->nodesIterator();
         SMESH_TNodeXYZ n1( nodeIt->next() );
         elemSize = 0;
         while ( nodeIt->more() )
@@ -594,7 +697,7 @@ bool SMESH_ElementSearcherImpl::getIntersParamOnLine(const gp_Lin&           lin
     anExtCC.Init( lineCurve, edge.Value() );
     if ( anExtCC.NbExtrema() > 0 && anExtCC.LowerDistance() <= tol)
     {
-      Quantity_Parameter pl, pe;
+      Standard_Real pl, pe;
       anExtCC.LowerDistanceParameters( pl, pe );
       param += pl;
       if ( ++nbInts == 2 )
@@ -679,7 +782,7 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF
           outerFace2 = angle2Face.begin()->second;
       }
     }
-    // store the found outer face and add its links to continue seaching from
+    // store the found outer face and add its links to continue searching from
     if ( outerFace2 )
     {
       _outerFaces.insert( outerFace2 );
@@ -723,6 +826,7 @@ FindElementsByPoint(const gp_Pnt&                      point,
                     vector< const SMDS_MeshElement* >& foundElements)
 {
   foundElements.clear();
+  _elementType = type;
 
   double tolerance = getTolerance();
 
@@ -756,14 +860,17 @@ FindElementsByPoint(const gp_Pnt&                      point,
   // =================================================================================
   else // elements more complex than 0D
   {
-    if ( !_ebbTree || _elementType != type )
+    if ( !_ebbTree[type] )
     {
-      if ( _ebbTree ) delete _ebbTree;
-      _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt, tolerance );
+      _ebbTree[_elementType] = new ElementBndBoxTree( *_mesh, type, _meshPartIt, tolerance );
     }
-    TIDSortedElemSet suspectElems;
-    _ebbTree->getElementsNearPoint( point, suspectElems );
-    TIDSortedElemSet::iterator elem = suspectElems.begin();
+    else
+    {
+      _ebbTree[ type ]->prepare();
+    }
+    vector< const SMDS_MeshElement* > suspectElems;
+    _ebbTree[ type ]->getElementsNearPoint( point, suspectElems );
+    vector< const SMDS_MeshElement* >::iterator elem = suspectElems.begin();
     for ( ; elem != suspectElems.end(); ++elem )
       if ( !SMESH_MeshAlgos::IsOut( *elem, point, tolerance ))
         foundElements.push_back( *elem );
@@ -784,35 +891,38 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt&       point,
                                           SMDSAbs_ElementType type )
 {
   const SMDS_MeshElement* closestElem = 0;
+  _elementType = type;
 
   if ( type == SMDSAbs_Face || type == SMDSAbs_Volume )
   {
-    if ( !_ebbTree || _elementType != type )
-    {
-      if ( _ebbTree ) delete _ebbTree;
-      _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt );
-    }
-    TIDSortedElemSet suspectElems;
-    _ebbTree->getElementsNearPoint( point, suspectElems );
+    ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
+    if ( !ebbTree )
+      ebbTree = new ElementBndBoxTree( *_mesh, type, _meshPartIt );
+    else
+      ebbTree->prepare();
 
-    if ( suspectElems.empty() && _ebbTree->maxSize() > 0 )
+    vector<const SMDS_MeshElement*> suspectElems;
+    ebbTree->getElementsNearPoint( point, suspectElems );
+
+    if ( suspectElems.empty() && ebbTree->maxSize() > 0 )
     {
-      gp_Pnt boxCenter = 0.5 * ( _ebbTree->getBox()->CornerMin() +
-                                 _ebbTree->getBox()->CornerMax() );
+      gp_Pnt boxCenter = 0.5 * ( ebbTree->getBox()->CornerMin() +
+                                 ebbTree->getBox()->CornerMax() );
       double radius = -1;
-      if ( _ebbTree->getBox()->IsOut( point.XYZ() ))
-        radius = point.Distance( boxCenter ) - 0.5 * _ebbTree->maxSize();
+      if ( ebbTree->getBox()->IsOut( point.XYZ() ))
+        radius = point.Distance( boxCenter ) - 0.5 * ebbTree->maxSize();
       if ( radius < 0 )
-        radius = _ebbTree->maxSize() / pow( 2., getTreeHeight()) / 2;
+        radius = ebbTree->maxSize() / pow( 2., getTreeHeight()) / 2;
       while ( suspectElems.empty() )
       {
-        _ebbTree->getElementsInSphere( point.XYZ(), radius, suspectElems );
+        ebbTree->prepare();
+        ebbTree->getElementsInSphere( point.XYZ(), radius, suspectElems );
         radius *= 1.1;
       }
     }
     double minDist = std::numeric_limits<double>::max();
     multimap< double, const SMDS_MeshElement* > dist2face;
-    TIDSortedElemSet::iterator elem = suspectElems.begin();
+    vector<const SMDS_MeshElement*>::iterator elem = suspectElems.begin();
     for ( ; elem != suspectElems.end(); ++elem )
     {
       double dist = SMESH_MeshAlgos::GetDistance( *elem, point );
@@ -869,12 +979,16 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt&       point,
 
 TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
 {
+  _elementType = SMDSAbs_Face;
+
   double tolerance = getTolerance();
-  if ( !_ebbTree || _elementType != SMDSAbs_Face )
-  {
-    if ( _ebbTree ) delete _ebbTree;
-    _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = SMDSAbs_Face, _meshPartIt );
-  }
+
+  ElementBndBoxTree*& ebbTree = _ebbTree[ SMDSAbs_Face ];
+  if ( !ebbTree )
+    ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
+
   // Algo: analyse transition of a line starting at the point through mesh boundary;
   // try three lines parallel to axis of the coordinate system and perform rough
   // analysis. If solution is not clear perform thorough analysis.
@@ -889,13 +1003,14 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
     gp_Ax1 lineAxis( point, axisDir[axis]);
     gp_Lin line    ( lineAxis );
 
-    TIDSortedElemSet suspectFaces; // faces possibly intersecting the line
-    _ebbTree->getElementsNearLine( lineAxis, suspectFaces );
+    vector<const SMDS_MeshElement*> suspectFaces; // faces possibly intersecting the line
+    if ( axis > 0 ) ebbTree->prepare();
+    ebbTree->getElementsNearLine( lineAxis, suspectFaces );
 
     // Intersect faces with the line
 
     map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
-    TIDSortedElemSet::iterator face = suspectFaces.begin();
+    vector<const SMDS_MeshElement*>::iterator face = suspectFaces.begin();
     for ( ; face != suspectFaces.end(); ++face )
     {
       // get face plane
@@ -1098,14 +1213,14 @@ void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1&
                                                      SMDSAbs_ElementType                type,
                                                      vector< const SMDS_MeshElement* >& foundElems)
 {
-  if ( !_ebbTree || _elementType != type )
-  {
-    if ( _ebbTree ) delete _ebbTree;
-    _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt );
-  }
-  TIDSortedElemSet suspectFaces; // elements possibly intersecting the line
-  _ebbTree->getElementsNearLine( line, suspectFaces );
-  foundElems.assign( suspectFaces.begin(), suspectFaces.end());
+  _elementType = type;
+  ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
+  if ( !ebbTree )
+    ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
+
+  ebbTree->getElementsNearLine( line, foundElems );
 }
 
 //=======================================================================
@@ -1119,14 +1234,63 @@ void SMESH_ElementSearcherImpl::GetElementsInSphere( const gp_XYZ&
                                                      SMDSAbs_ElementType                type,
                                                      vector< const SMDS_MeshElement* >& foundElems)
 {
-  if ( !_ebbTree || _elementType != type )
+  _elementType = type;
+  ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
+  if ( !ebbTree )
+    ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
+  else
+    ebbTree->prepare();
+
+  ebbTree->getElementsInSphere( center, radius, foundElems );
+}
+
+//=======================================================================
+/*
+ * \brief Return a projection of a given point to a mesh.
+ *        Optionally return the closest element
+ */
+//=======================================================================
+
+gp_XYZ SMESH_ElementSearcherImpl::Project(const gp_Pnt&            point,
+                                          SMDSAbs_ElementType      type,
+                                          const SMDS_MeshElement** closestElem)
+{
+  _elementType = type;
+  if ( _mesh->GetMeshInfo().NbElements( _elementType ) == 0 )
+    throw SALOME_Exception( LOCALIZED( "No elements of given type in the mesh" ));
+
+  ElementBndBoxTree*& ebbTree = _ebbTree[ _elementType ];
+  if ( !ebbTree )
+    ebbTree = new ElementBndBoxTree( *_mesh, _elementType );
+
+  gp_XYZ p = point.XYZ();
+  ElementBndBoxTree* ebbLeaf = ebbTree->getLeafAtPoint( p );
+  const Bnd_B3d* box = ebbLeaf->getBox();
+  double radius = ( box->CornerMax() - box->CornerMin() ).Modulus();
+
+  vector< const SMDS_MeshElement* > elems;
+  ebbTree->getElementsInSphere( p, radius, elems );
+  while ( elems.empty() )
   {
-    if ( _ebbTree ) delete _ebbTree;
-    _ebbTree = new ElementBndBoxTree( *_mesh, _elementType = type, _meshPartIt );
+    radius *= 1.5;
+    ebbTree->getElementsInSphere( p, radius, elems );
   }
-  TIDSortedElemSet suspectFaces; // elements possibly intersecting the line
-  _ebbTree->getElementsInSphere( center, radius, suspectFaces );
-  foundElems.assign( suspectFaces.begin(), suspectFaces.end() );
+  gp_XYZ proj, bestProj;
+  const SMDS_MeshElement* elem = 0;
+  double minDist = 2 * radius;
+  for ( size_t i = 0; i < elems.size(); ++i )
+  {
+    double d = SMESH_MeshAlgos::GetDistance( elems[i], p, &proj );
+    if ( d < minDist )
+    {
+      bestProj = proj;
+      elem = elems[i];
+      minDist = d;
+    }
+  }
+  if ( closestElem ) *closestElem = elem;
+
+  return bestProj;
 }
 
 //=======================================================================
@@ -1163,8 +1327,8 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
       gp_Vec edge2( xyz[i+1], xyz[(i+2)%nbNodes] );
       faceNorm += edge1 ^ edge2;
     }
-    double normSize = faceNorm.Magnitude();
-    if ( normSize <= tol )
+    double fNormSize = faceNorm.Magnitude();
+    if ( fNormSize <= tol )
     {
       // degenerated face: point is out if it is out of all face edges
       for ( i = 0; i < nbNodes; ++i )
@@ -1175,7 +1339,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
       }
       return true;
     }
-    faceNorm /= normSize;
+    faceNorm /= fNormSize;
 
     // check if the point lays on face plane
     gp_Vec n2p( xyz[0], point );
@@ -1204,9 +1368,10 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     // to find intersections of the ray with the boundary.
     gp_Vec ray = n2p;
     gp_Vec plnNorm = ray ^ faceNorm;
-    normSize = plnNorm.Magnitude();
-    if ( normSize <= tol ) return false; // point coincides with the first node
-    plnNorm /= normSize;
+    double n2pSize = plnNorm.Magnitude();
+    if ( n2pSize <= tol ) return false; // point coincides with the first node
+    if ( n2pSize * n2pSize > fNormSize * 100 ) return true; // point is very far
+    plnNorm /= n2pSize;
     // for each node of the face, compute its signed distance to the cutting plane
     vector<double> dist( nbNodes + 1);
     for ( i = 0; i < nbNodes; ++i )
@@ -1252,7 +1417,7 @@ bool SMESH_MeshAlgos::IsOut( const SMDS_MeshElement* element, const gp_Pnt& poin
     if ( rClosest > 0. && rClosest < 1. ) // not node intersection
       return out;
 
-    // ray pass through a face node; analyze transition through an adjacent edge
+    // the ray passes through a face node; analyze transition through an adjacent edge
     gp_Pnt p1 = xyz[ (rClosest == 0.) ? ((iClosest+nbNodes-1) % nbNodes) : (iClosest+1) ];
     gp_Pnt p2 = xyz[ (rClosest == 0.) ? iClosest : ((iClosest+2) % nbNodes) ];
     gp_Vec edgeAdjacent( p1, p2 );
@@ -1375,17 +1540,19 @@ namespace
 //=======================================================================
 
 double SMESH_MeshAlgos::GetDistance( const SMDS_MeshElement* elem,
-                                     const gp_Pnt&           point )
+                                     const gp_Pnt&           point,
+                                     gp_XYZ*                 closestPnt )
 {
   switch ( elem->GetType() )
   {
   case SMDSAbs_Volume:
-    return GetDistance( dynamic_cast<const SMDS_MeshVolume*>( elem ), point);
+    return GetDistance( dynamic_cast<const SMDS_MeshVolume*>( elem ), point, closestPnt );
   case SMDSAbs_Face:
-    return GetDistance( dynamic_cast<const SMDS_MeshFace*>( elem ), point);
+    return GetDistance( dynamic_cast<const SMDS_MeshFace*>( elem ), point, closestPnt );
   case SMDSAbs_Edge:
-    return GetDistance( dynamic_cast<const SMDS_MeshEdge*>( elem ), point);
+    return GetDistance( dynamic_cast<const SMDS_MeshEdge*>( elem ), point, closestPnt );
   case SMDSAbs_Node:
+    if ( closestPnt ) *closestPnt = SMESH_TNodeXYZ( elem );
     return point.Distance( SMESH_TNodeXYZ( elem ));
   default:;
   }
@@ -1401,9 +1568,10 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshElement* elem,
 //=======================================================================
 
 double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
-                                     const gp_Pnt&        point )
+                                     const gp_Pnt&        point,
+                                     gp_XYZ*              closestPnt )
 {
-  double badDistance = -1;
+  const double badDistance = -1;
   if ( !face ) return badDistance;
 
   // coordinates of nodes (medium nodes, if any, ignored)
@@ -1447,7 +1615,7 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
   trsf.Transforms( tmpPnt );
   gp_XY point2D( tmpPnt.X(), tmpPnt.Z() );
 
-  // loop on segments of the face to analyze point position ralative to the face
+  // loop on edges of the face to analyze point position ralative to the face
   set< PointPos > pntPosSet;
   for ( size_t i = 1; i < xy.size(); ++i )
   {
@@ -1457,31 +1625,40 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
 
   // compute distance
   PointPos pos = *pntPosSet.begin();
-  // cout << "Face " << face->GetID() << " DIST: ";
   switch ( pos._name )
   {
-  case POS_LEFT: {
-    // point is most close to a segment
-    gp_Vec p0p1( point, xyz[ pos._index ] );
-    gp_Vec p1p2( xyz[ pos._index ], xyz[ pos._index+1 ]); // segment vector
-    p1p2.Normalize();
-    double projDist = p0p1 * p1p2; // distance projected to the segment
-    gp_Vec projVec = p1p2 * projDist;
-    gp_Vec distVec = p0p1 - projVec;
-    // cout << distVec.Magnitude()  << ", SEG " << face->GetNode(pos._index)->GetID()
-    //      << " - " << face->GetNodeWrap(pos._index+1)->GetID() << endl;
-    return distVec.Magnitude();
+  case POS_LEFT:
+  {
+    // point is most close to an edge
+    gp_Vec edge( xyz[ pos._index ], xyz[ pos._index+1 ]);
+    gp_Vec n1p ( xyz[ pos._index ], point  );
+    double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
+    // projection of the point on the edge
+    gp_XYZ proj = ( 1. - u ) * xyz[ pos._index ] + u * xyz[ pos._index+1 ];
+    if ( closestPnt ) *closestPnt = proj;
+    return point.Distance( proj );
   }
-  case POS_RIGHT: {
+  case POS_RIGHT:
+  {
     // point is inside the face
     double distToFacePlane = tmpPnt.Y();
-    // cout << distToFacePlane << ", INSIDE " << endl;
+    if ( closestPnt )
+    {
+      if ( distToFacePlane < std::numeric_limits<double>::min() ) {
+        *closestPnt = point.XYZ();
+      }
+      else {
+        tmpPnt.SetY( 0 );
+        trsf.Inverted().Transforms( tmpPnt );
+        *closestPnt = tmpPnt;
+      }
+    }
     return Abs( distToFacePlane );
   }
-  case POS_VERTEX: {
+  case POS_VERTEX:
+  {
     // point is most close to a node
     gp_Vec distVec( point, xyz[ pos._index ]);
-    // cout << distVec.Magnitude()  << " VERTEX " << face->GetNode(pos._index)->GetID() << endl;
     return distVec.Magnitude();
   }
   default:;
@@ -1495,7 +1672,9 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshFace* face,
  */
 //=======================================================================
 
-double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg, const gp_Pnt& point )
+double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg,
+                                     const gp_Pnt&        point,
+                                     gp_XYZ*              closestPnt )
 {
   double dist = Precision::Infinite();
   if ( !seg ) return dist;
@@ -1514,13 +1693,16 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg, const gp_Pnt& poi
     double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
     if ( u <= 0. ) {
       dist = Min( dist, n1p.SquareMagnitude() );
+      if ( closestPnt ) *closestPnt = xyz[i-1];
     }
     else if ( u >= 1. ) {
       dist = Min( dist, point.SquareDistance( xyz[i] ));
+      if ( closestPnt ) *closestPnt = xyz[i];
     }
     else {
       gp_XYZ proj = ( 1. - u ) * xyz[i-1] + u * xyz[i]; // projection of the point on the edge
       dist = Min( dist, point.SquareDistance( proj ));
+      if ( closestPnt ) *closestPnt = proj;
     }
   }
   return Sqrt( dist );
@@ -1534,7 +1716,9 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshEdge* seg, const gp_Pnt& poi
  */
 //=======================================================================
 
-double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt& point )
+double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume,
+                                     const gp_Pnt&          point,
+                                     gp_XYZ*                closestPnt )
 {
   SMDS_VolumeTool vTool( volume );
   vTool.SetExternalNormal();
@@ -1542,6 +1726,8 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt
 
   double n[3], bc[3];
   double minDist = 1e100, dist;
+  gp_XYZ closeP = point.XYZ();
+  bool isOut = false;
   for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
   {
     // skip a facet with normal not "looking at" the point
@@ -1558,23 +1744,34 @@ double SMESH_MeshAlgos::GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt
     case 3:
     {
       SMDS_FaceOfNodes tmpFace( nodes[0], nodes[ 1*iQ ], nodes[ 2*iQ ] );
-      dist = GetDistance( &tmpFace, point );
+      dist = GetDistance( &tmpFace, point, closestPnt );
       break;
     }
     case 4:
     {
       SMDS_FaceOfNodes tmpFace( nodes[0], nodes[ 1*iQ ], nodes[ 2*iQ ], nodes[ 3*iQ ]);
-      dist = GetDistance( &tmpFace, point );
+      dist = GetDistance( &tmpFace, point, closestPnt );
       break;
     }
     default:
       vector<const SMDS_MeshNode *> nvec( nodes, nodes + vTool.NbFaceNodes( iF ));
       SMDS_PolygonalFaceOfNodes tmpFace( nvec );
-      dist = GetDistance( &tmpFace, point );
+      dist = GetDistance( &tmpFace, point, closestPnt );
     }
-    minDist = Min( minDist, dist );
+    if ( dist < minDist )
+    {
+      minDist = dist;
+      isOut = true;
+      if ( closestPnt ) closeP = *closestPnt;
+    }
+  }
+  if ( isOut )
+  {
+    if ( closestPnt ) *closestPnt = closeP;
+    return minDist;
   }
-  return minDist;
+
+  return 0; // point is inside the volume
 }
 
 //================================================================================
@@ -1765,3 +1962,12 @@ SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh&
 {
   return new SMESH_ElementSearcherImpl( mesh, tolerance, elemIt );
 }
+
+// TMP for ASERIS in V8_2_BR -- to remove when merging to master
+void SMESH_MeshAlgos::DeMerge(const SMDS_MeshElement*              elem,
+                              std::vector< const SMDS_MeshNode* >& newNodes,
+                              std::vector< const SMDS_MeshNode* >& noMergeNodes)
+{
+// TMP for ASERIS in V8_2_BR -- to remove when merging to master
+}
+// TMP for ASERIS in V8_2_BR -- to remove when merging to master
index b6c3661b0965ddae6725e62a7d78d095e7d23b46..22498c0e2931a98a835890fa1ecd6b9a4d8b3c96 100644 (file)
@@ -100,6 +100,15 @@ struct SMESHUtils_EXPORT SMESH_ElementSearcher
    * \brief Find out if the given point is out of closed 2D mesh.
    */
   virtual TopAbs_State GetPointState(const gp_Pnt& point) = 0;
+
+  /*!
+   * \brief Return a projection of a given point to a 2D mesh.
+   *        Optionally return the closest face
+   */
+  virtual gp_XYZ Project(const gp_Pnt&            point,
+                         SMDSAbs_ElementType      type,
+                         const SMDS_MeshElement** closestFace= 0) = 0;
+
   virtual ~SMESH_ElementSearcher();
 };
 
@@ -112,16 +121,16 @@ namespace SMESH_MeshAlgos
   bool IsOut( const SMDS_MeshElement* element, const gp_Pnt& point, double tol );
 
   SMESHUtils_EXPORT
-  double GetDistance( const SMDS_MeshElement* elem, const gp_Pnt& point );
+  double GetDistance( const SMDS_MeshElement* elem, const gp_Pnt& point, gp_XYZ* closestPnt = 0 );
 
   SMESHUtils_EXPORT
-  double GetDistance( const SMDS_MeshEdge* edge, const gp_Pnt& point );
+  double GetDistance( const SMDS_MeshEdge* edge, const gp_Pnt& point, gp_XYZ* closestPnt = 0 );
 
   SMESHUtils_EXPORT
-  double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point );
+  double GetDistance( const SMDS_MeshFace* face, const gp_Pnt& point, gp_XYZ* closestPnt = 0 );
 
   SMESHUtils_EXPORT
-  double GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt& point );
+  double GetDistance( const SMDS_MeshVolume* volume, const gp_Pnt& point, gp_XYZ* closestPnt = 0 );
 
   SMESHUtils_EXPORT
   void GetBarycentricCoords( const gp_XY& point,
@@ -206,6 +215,16 @@ namespace SMESH_MeshAlgos
                                  CoincidentFreeBorders & foundFreeBordes);
   
 
-} // SMESH_MeshAlgos
+  /*!
+   * \brief Find nodes whose merge makes the element invalid
+   *
+   * (Implemented in SMESH_DeMerge.cxx)
+   */
+  SMESHUtils_EXPORT
+  void DeMerge(const SMDS_MeshElement*              elem,
+               std::vector< const SMDS_MeshNode* >& newNodes,
+               std::vector< const SMDS_MeshNode* >& noMergeNodes);
+
+} // namespace SMESH_MeshAlgos
 
 #endif
index 1f987213a6fd97314b8898215c6e4fce757e3e8d..71e587caa6f566ecb4432640588176d0a7475bfc 100644 (file)
@@ -32,6 +32,12 @@ void SMESH::doNothing(const char* txt)
 {
   MESSAGE( txt << " " << __FILE__ << ": " << __LINE__ );
 }
+
+const char* SMESH::returnError(const char* txt)
+{
+  return txt;
+}
+
 // ------------------------------------------------------------------
 #include "SMESH_ComputeError.hxx"
 
index ccdf3b1dadcf4b2ace94d8f4b3f8a254df3abdec..1443c7594a0a2aa3dc7fd43068ee6740f9f70be6 100644 (file)
@@ -104,6 +104,7 @@ namespace SMESH
 {
   SMESHUtils_EXPORT void throwSalomeEx(const char* txt);
   SMESHUtils_EXPORT void doNothing(const char* txt);
+  SMESHUtils_EXPORT const char* returnError(const char* txt);
 }
 
 #endif
index 77c095cc17be56cee81a2854fa400945cf35d4be..c9be990f65b274515dd082b134ac98494fa3619a 100644 (file)
@@ -169,6 +169,7 @@ struct SMESH_TNodeXYZ : public gp_XYZ
   double SquareDistance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).SquareModulus(); }
   bool operator==(const SMESH_TNodeXYZ& other) const { return _node == other._node; }
 };
+typedef SMESH_TNodeXYZ SMESH_NodeXYZ;
 
 //--------------------------------------------------
 /*!
index a0c252bd3c9770a33337b94f906d561da80bdb84..7ef2f4633a874324b8ad4062caaabf77b36ef40d 100644 (file)
@@ -184,7 +184,7 @@ namespace MeshEditor_I {
 
   //=============================================================================
   /*!
-   * \brief Deleter of theNodeSearcher at any compute event occured
+   * \brief Deleter of theNodeSearcher at any compute event occurred
    */
   //=============================================================================
 
@@ -467,9 +467,9 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 //================================================================================
 /*!
  * \brief Increment mesh modif time and optionally record that the performed
- *        modification may influence futher mesh re-compute.
+ *        modification may influence further mesh re-compute.
  *  \param [in] isReComputeSafe - true if the modification does not influence
- *              futher mesh re-compute
+ *              further mesh re-compute
  */
 //================================================================================
 
@@ -501,7 +501,7 @@ void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
  * \brief Initialize and return myPreviewMesh
  *  \param previewElements - type of elements to show in preview
  *
- *  WARNING: call it once par a method!
+ *  WARNING: call it once per method!
  */
 //================================================================================
 
@@ -669,7 +669,7 @@ void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
 
 //=======================================================================
 /*
- * Returns description of an error/warning occured during the last operation
+ * Returns description of an error/warning occurred during the last operation
  * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
  */
 //=======================================================================
@@ -4159,7 +4159,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
-                                     const SMESH::ListOfIDSources&     NodesToKeep)
+                                     const SMESH::ListOfIDSources&     NodesToKeep,
+                                     CORBA::Boolean                    AvoidMakingHoles)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -4203,9 +4204,9 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
     aTPythonDump << aNodeGroup;
   }
 
-  getEditor().MergeNodes( aListOfListOfNodes );
+  getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
 
-  aTPythonDump << "], " << NodesToKeep << ")";
+  aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
 
   declareMeshModified( /*isReComputeSafe=*/false );
 
@@ -5117,7 +5118,6 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
                 << ide << ", " << newIDs << " )";
 
-  MESSAGE("ChangeElementNodes");
   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
 
   declareMeshModified( /*isReComputeSafe=*/ !res );
@@ -6280,7 +6280,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
-  MESSAGE("AffectedElemGroupsInRegion");
   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
   bool isEdgeGroup = false;
   bool isFaceGroup = false;
@@ -6309,7 +6308,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   if (aResult)
   {
     int lg = anAffected.size();
-    MESSAGE("lg="<< lg);
     SMESH::long_array_var volumeIds = new SMESH::long_array;
     volumeIds->length(lg);
     SMESH::long_array_var faceIds = new SMESH::long_array;
@@ -6658,7 +6656,7 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryMesh( "
@@ -6722,7 +6720,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     else
       groupsOfThisMesh[ nbGroups++ ] = groups[i];
     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
-      THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
+      THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
   }
   groupsOfThisMesh->length( nbGroups );
   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
@@ -6816,7 +6814,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryElements( "
@@ -6833,3 +6831,128 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
+
+//================================================================================
+/*!
+ * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+ *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+ *        plane passing through pairs of points specified by each PolySegment structure.
+ *        If there are several paths connecting a pair of points, the shortest path is
+ *        selected by the module. Position of the cutting plane is defined by the two
+ *        points and an optional vector lying on the plane specified by a PolySegment.
+ *        By default the vector is defined by Mesh module as following. A middle point
+ *        of the two given points is computed. The middle point is projected to the mesh.
+ *        The vector goes from the middle point to the projection point. In case of planar
+ *        mesh, the vector is normal to the mesh.
+ *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+ *        Return the used vector and position of the middle point.
+ *  \param [in] groupName - optional name of a group where created mesh segments will
+ *        be added.
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
+                                      const char*                theGroupName)
+  throw (SALOME::SALOME_Exception)
+{
+  if ( theSegments.length() == 0 )
+    THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
+  if ( myMesh->NbFaces() == 0 )
+    THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
+
+  SMESH_TRY;
+  initData(/*deleteSearchers=*/false);
+
+  SMESHDS_Group* groupDS = 0;
+  if ( myIsPreviewMode ) // copy faces to the tmp mesh
+  {
+    TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
+    SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
+    while ( faceIt->more() )
+      tmpMesh->Copy( faceIt->next() );
+  }
+  else if ( theGroupName[0] ) // find/create a group of segments
+  {
+    SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
+    while ( !groupDS && grpIt->more() )
+    {
+      SMESH_Group* group = grpIt->next();
+      if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
+           strcmp( group->GetName(), theGroupName ) == 0 )
+      {
+        groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
+      }
+    }
+    if ( !groupDS )
+    {
+      SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
+
+      if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
+        groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
+    }
+  }
+
+  // convert input polySegments
+  ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
+  for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+  {
+    SMESH::PolySegment&               segIn = theSegments[ i ];
+    ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
+    segOut.myNode1[0] = getMeshDS()->FindNode( segIn.node1ID1 );
+    segOut.myNode2[0] = getMeshDS()->FindNode( segIn.node1ID2 );
+    segOut.myNode1[1] = getMeshDS()->FindNode( segIn.node2ID1 );
+    segOut.myNode2[1] = getMeshDS()->FindNode( segIn.node2ID2 );
+    segOut.myVector.SetCoord( segIn.vector.PS.x,
+                              segIn.vector.PS.y,
+                              segIn.vector.PS.z );
+    if ( !segOut.myNode1[0] )
+      THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
+                                    SALOME::BAD_PARAM );
+    if ( !segOut.myNode1[1] )
+      THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
+                                    SALOME::BAD_PARAM );
+  }
+
+  // get a static ElementSearcher
+  SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
+  theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
+  if ( !theElementSearcher )
+    theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
+
+  // compute
+  getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
+
+  // return vectors
+  if ( myIsPreviewMode )
+  {
+    for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+    {
+      SMESH::PolySegment&             segOut = theSegments[ i ];
+      ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
+      segOut.vector.PS.x = segIn.myVector.X();
+      segOut.vector.PS.y = segIn.myVector.Y();
+      segOut.vector.PS.z = segIn.myVector.Z();
+    }
+  }
+  else
+  {
+    TPythonDump() << "_segments = []";
+    for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+    {
+      SMESH::PolySegment& segIn = theSegments[ i ];
+      TPythonDump() << "_segments.append( SMESH.PolySegment( "
+                    << segIn.node1ID1 << ", "
+                    << segIn.node1ID2 << ", "
+                    << segIn.node2ID1 << ", "
+                    << segIn.node2ID2 << ", "
+                    << "smeshBuilder.MakeDirStruct( "
+                    << segIn.vector.PS.x << ", "
+                    << segIn.vector.PS.y << ", "
+                    << segIn.vector.PS.z << ")))";
+    }
+    TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return;
+}
index dd1212d8c602ee089d674495ced42429d2c3b727..b8cfa0064d03dae3d289bdfc9ff661a65867a0b2 100644 (file)
@@ -83,7 +83,7 @@ public:
    */
   void ClearLastCreated() throw (SALOME::SALOME_Exception);
   /*!
-   * \brief Returns description of an error/warning occured during the last operation
+   * \brief Returns description of an error/warning occurred during the last operation
    */
   SMESH::ComputeError* GetLastError() throw (SALOME::SALOME_Exception);
 
@@ -495,7 +495,8 @@ public:
                                     CORBA::Boolean                 SeparateCornersAndMedium)
     throw (SALOME::SALOME_Exception);
   void MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
-                   const SMESH::ListOfIDSources&     NodesToKeep )
+                   const SMESH::ListOfIDSources&     NodesToKeep,
+                   CORBA::Boolean                    AvoidMakingHoles )
     throw (SALOME::SALOME_Exception);
   void FindEqualElements(SMESH::SMESH_IDSource_ptr      Object,
                          SMESH::array_of_long_array_out GroupsOfElementsID)
@@ -815,7 +816,7 @@ public:
                       const char* groupName,
                       const SMESH::double_array& theNodesCoords,
                       SMESH::array_of_long_array_out GroupsOfNodes)
-  throw (SALOME::SALOME_Exception);
+    throw (SALOME::SALOME_Exception);
 
   /*!
    * \brief Generated skin mesh (containing 2D cells) from 3D mesh
@@ -843,7 +844,28 @@ public:
                                    SMESH::SMESH_Group_out group)
     throw (SALOME::SALOME_Exception);
 
-private: //!< private methods
+  /*!
+   * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+   *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+   *        plane passing through pairs of points specified by each PolySegment structure.
+   *        If there are several paths connecting a pair of points, the shortest path is
+   *        selected by the module. Position of the cutting plane is defined by the two
+   *        points and an optional vector lying on the plane specified by a PolySegment.
+   *        By default the vector is defined by Mesh module as following. A middle point
+   *        of the two given points is computed. The middle point is projected to the mesh.
+   *        The vector goes from the middle point to the projection point. In case of planar
+   *        mesh, the vector is normal to the mesh.
+   *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+   *        Return the used vector and position of the middle point.
+   *  \param [in] groupName - optional name of a group where created mesh segments will
+   *        be added.
+   */
+  void MakePolyLine(SMESH::ListOfPolySegments& segments,
+                    const char*               groupName)
+    throw (SALOME::SALOME_Exception);
+
+
+ private: //!< private methods
 
   ::SMESH_MeshEditor& getEditor();
 
index e779c7a7ab8d220c2e8f2afaa8d66ae18f7f6fc9..0deca2ea8210546ea8393f9105cf89e561d0d846 100644 (file)
 ## @defgroup l1_creating  Creating meshes
 ## @{
 ##   @defgroup l2_impexp     Importing and exporting meshes
+##   @{
+##     @details
+##     These are methods of class \ref smeshBuilder.smeshBuilder "smeshBuilder"
+##   @}
 ##   @defgroup l2_construct  Constructing meshes
 ##   @defgroup l2_algorithms Defining Algorithms
 ##   @{
@@ -45,8 +49,7 @@
 ##     @defgroup l3_hypos_additi Additional Hypotheses
 
 ##   @}
-##   @defgroup l2_submeshes Constructing submeshes
-##   @defgroup l2_compounds Building Compounds
+##   @defgroup l2_submeshes Constructing sub-meshes
 ##   @defgroup l2_editing   Editing Meshes
 
 ## @}
@@ -55,7 +58,6 @@
 ## @defgroup l1_grouping  Grouping elements
 ## @{
 ##   @defgroup l2_grps_create Creating groups
-##   @defgroup l2_grps_edit   Editing groups
 ##   @defgroup l2_grps_operon Using operations on groups
 ##   @defgroup l2_grps_delete Deleting Groups
 
 ##   @defgroup l2_modif_edit     Modifying nodes and elements
 ##   @defgroup l2_modif_renumber Renumbering nodes and elements
 ##   @defgroup l2_modif_trsf     Transforming meshes (Translation, Rotation, Symmetry, Sewing, Merging)
-##   @defgroup l2_modif_movenode Moving nodes
-##   @defgroup l2_modif_throughp Mesh through point
 ##   @defgroup l2_modif_unitetri Uniting triangles
 ##   @defgroup l2_modif_cutquadr Cutting elements
 ##   @defgroup l2_modif_changori Changing orientation of elements
 ##   @defgroup l2_modif_smooth   Smoothing
 ##   @defgroup l2_modif_extrurev Extrusion and Revolution
-##   @defgroup l2_modif_patterns Pattern mapping
 ##   @defgroup l2_modif_tofromqu Convert to/from Quadratic Mesh
+##   @defgroup l2_modif_duplicat Duplication of nodes and elements (to emulate cracks)
 
 ## @}
 ## @defgroup l1_measurements Measurements
@@ -91,6 +91,8 @@ import SALOME
 import SALOMEDS
 import os
 
+## Private class used to workaround a problem that sometimes isinstance(m, Mesh) returns False
+#
 class MeshMeta(type):
     def __instancecheck__(cls, inst):
         """Implement isinstance(inst, cls)."""
@@ -104,7 +106,7 @@ class MeshMeta(type):
 ## @addtogroup l1_auxiliary
 ## @{
 
-## Converts an angle from degrees to radians
+## Convert an angle from degrees to radians
 def DegreesToRadians(AngleInDegrees):
     from math import pi
     return AngleInDegrees * pi / 180.0
@@ -145,19 +147,19 @@ def ParseParameters(*args):
     Result.append( hasVariables )
     return Result
 
-# Parse parameters converting variables to radians
+## Parse parameters while converting variables to radians
 def ParseAngles(*args):
     return ParseParameters( *( args + (DegreesToRadians, )))
 
-# Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
-# Parameters are stored in PointStruct.parameters attribute
+## Substitute PointStruct.__init__() to create SMESH.PointStruct using notebook variables.
+#  Parameters are stored in PointStruct.parameters attribute
 def __initPointStruct(point,*args):
     point.x, point.y, point.z, point.parameters,hasVars = ParseParameters(*args)
     pass
 SMESH.PointStruct.__init__ = __initPointStruct
 
-# Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
-# Parameters are stored in AxisStruct.parameters attribute
+## Substitute AxisStruct.__init__() to create SMESH.AxisStruct using notebook variables.
+#  Parameters are stored in AxisStruct.parameters attribute
 def __initAxisStruct(ax,*args):
     if len( args ) != 6:
         raise RuntimeError,\
@@ -167,6 +169,7 @@ def __initAxisStruct(ax,*args):
 SMESH.AxisStruct.__init__ = __initAxisStruct
 
 smeshPrecisionConfusion = 1.e-07
+## Compare real values using smeshPrecisionConfusion as tolerance
 def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
     if abs(val1 - val2) < tol:
         return True
@@ -174,7 +177,7 @@ def IsEqual(val1, val2, tol=smeshPrecisionConfusion):
 
 NO_NAME = "NoName"
 
-## Gets object name
+## Return object name
 def GetName(obj):
     if obj:
         # object not null
@@ -207,7 +210,7 @@ def GetName(obj):
         pass
     raise RuntimeError, "Null or invalid object"
 
-## Prints error message if a hypothesis was not assigned.
+## Print error message if a hypothesis was not assigned.
 def TreatHypoStatus(status, hypName, geomName, isAlgo, mesh):
     if isAlgo:
         hypType = "algorithm"
@@ -271,7 +274,7 @@ def AssureGeomPublished(mesh, geom, name=''):
             mesh.geompyD.init_geom( mesh.smeshpyD.GetCurrentStudy())
         ## get a name
         if not name and geom.GetShapeType() != geomBuilder.GEOM.COMPOUND:
-            # for all groups SubShapeName() returns "Compound_-1"
+            # for all groups SubShapeName() return "Compound_-1"
             name = mesh.geompyD.SubShapeName(geom, mesh.geom)
         if not name:
             name = "%s_%s"%(geom.GetShapeType(), id(geom)%10000)
@@ -376,20 +379,22 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
     ## Dump component to the Python script
     #  This method overrides IDL function to allow default values for the parameters.
+    #  @ingroup l1_auxiliary
     def DumpPython(self, theStudy, theIsPublished=True, theIsMultiFile=True):
         return SMESH._objref_SMESH_Gen.DumpPython(self, theStudy, theIsPublished, theIsMultiFile)
 
     ## Set mode of DumpPython(), \a historical or \a snapshot.
-    # In the \a historical mode, the Python Dump script includes all commands
-    # performed by SMESH engine. In the \a snapshot mode, commands
-    # relating to objects removed from the Study are excluded from the script
-    # as well as commands not influencing the current state of meshes
+    #  In the \a historical mode, the Python Dump script includes all commands
+    #  performed by SMESH engine. In the \a snapshot mode, commands
+    #  relating to objects removed from the Study are excluded from the script
+    #  as well as commands not influencing the current state of meshes
+    #  @ingroup l1_auxiliary
     def SetDumpPythonHistorical(self, isHistorical):
         if isHistorical: val = "true"
         else:            val = "false"
         SMESH._objref_SMESH_Gen.SetOption(self, "historical_python_dump", val)
 
-    ## Sets the current study and Geometry component
+    ## Set the current study and Geometry component
     #  @ingroup l1_auxiliary
     def init_smesh(self,theStudy,geompyD = None):
         #print "init_smesh"
@@ -398,7 +403,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             global notebook
             notebook.myStudy = theStudy
 
-    ## Creates a mesh. This can be either an empty mesh, possibly having an underlying geometry,
+    ## Create a mesh. This can be either an empty mesh, possibly having an underlying geometry,
     #  or a mesh wrapping a CORBA mesh given as a parameter.
     #  @param obj either (1) a CORBA mesh (SMESH._objref_SMESH_Mesh) got e.g. by calling
     #         salome.myStudy.FindObjectID("0:1:2:3").GetObject() or
@@ -412,15 +417,15 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             obj,name = name,obj
         return Mesh(self,self.geompyD,obj,name)
 
-    ## Returns a long value from enumeration
-    #  @ingroup l1_controls
+    ## Return a long value from enumeration
+    #  @ingroup l1_auxiliary
     def EnumToLong(self,theItem):
         return theItem._v
 
-    ## Returns a string representation of the color.
+    ## Return a string representation of the color.
     #  To be used with filters.
     #  @param c color value (SALOMEDS.Color)
-    #  @ingroup l1_controls
+    #  @ingroup l1_auxiliary
     def ColorToString(self,c):
         val = ""
         if isinstance(c, SALOMEDS.Color):
@@ -431,7 +436,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             raise ValueError, "Color value should be of string or SALOMEDS.Color type"
         return val
 
-    ## Gets PointStruct from vertex
+    ## Get PointStruct from vertex
     #  @param theVertex a GEOM object(vertex)
     #  @return SMESH.PointStruct
     #  @ingroup l1_auxiliary
@@ -439,7 +444,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         [x, y, z] = self.geompyD.PointCoordinates(theVertex)
         return PointStruct(x,y,z)
 
-    ## Gets DirStruct from vector
+    ## Get DirStruct from vector
     #  @param theVector a GEOM object(vector)
     #  @return SMESH.DirStruct
     #  @ingroup l1_auxiliary
@@ -454,7 +459,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         dirst = DirStruct(pnt)
         return dirst
 
-    ## Makes DirStruct from a triplet
+    ## Make DirStruct from a triplet
     #  @param x,y,z vector components
     #  @return SMESH.DirStruct
     #  @ingroup l1_auxiliary
@@ -497,7 +502,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     # From SMESH_Gen interface:
     # ------------------------
 
-    ## Sets the given name to the object
+    ## Set the given name to the object
     #  @param obj the object to rename
     #  @param name a new object name
     #  @ingroup l1_auxiliary
@@ -509,17 +514,17 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         ior  = salome.orb.object_to_string(obj)
         SMESH._objref_SMESH_Gen.SetName(self, ior, name)
 
-    ## Sets the current mode
+    ## Set the current mode
     #  @ingroup l1_auxiliary
     def SetEmbeddedMode( self,theMode ):
         SMESH._objref_SMESH_Gen.SetEmbeddedMode(self,theMode)
 
-    ## Gets the current mode
+    ## Get the current mode
     #  @ingroup l1_auxiliary
     def IsEmbeddedMode(self):
         return SMESH._objref_SMESH_Gen.IsEmbeddedMode(self)
 
-    ## Sets the current study. Calling SetCurrentStudy( None ) allows to
+    ## Set the current study. Calling SetCurrentStudy( None ) allows to
     #  switch OFF automatic pubilishing in the Study of mesh objects.
     #  @ingroup l1_auxiliary
     def SetCurrentStudy( self, theStudy, geompyD = None ):
@@ -542,12 +547,12 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
             pass
         pass
 
-    ## Gets the current study
+    ## Get the current study
     #  @ingroup l1_auxiliary
     def GetCurrentStudy(self):
         return SMESH._objref_SMESH_Gen.GetCurrentStudy(self)
 
-    ## Creates a Mesh object importing data from the given UNV file
+    ## Create a Mesh object importing data from the given UNV file
     #  @return an instance of Mesh class
     #  @ingroup l2_impexp
     def CreateMeshesFromUNV( self,theFileName ):
@@ -555,7 +560,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
         return aMesh
 
-    ## Creates a Mesh object(s) importing data from the given MED file
+    ## Create a Mesh object(s) importing data from the given MED file
     #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromMED( self,theFileName ):
@@ -563,7 +568,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
-    ## Creates a Mesh object(s) importing data from the given SAUV file
+    ## Create a Mesh object(s) importing data from the given SAUV file
     #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromSAUV( self,theFileName ):
@@ -571,7 +576,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
-    ## Creates a Mesh object importing data from the given STL file
+    ## Create a Mesh object importing data from the given STL file
     #  @return an instance of Mesh class
     #  @ingroup l2_impexp
     def CreateMeshesFromSTL( self, theFileName ):
@@ -579,7 +584,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMesh = Mesh(self, self.geompyD, aSmeshMesh)
         return aMesh
 
-    ## Creates Mesh objects importing data from the given CGNS file
+    ## Create Mesh objects importing data from the given CGNS file
     #  @return a tuple ( list of Mesh class instances, SMESH.DriverMED_ReadStatus )
     #  @ingroup l2_impexp
     def CreateMeshesFromCGNS( self, theFileName ):
@@ -587,7 +592,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aMeshes = [ Mesh(self, self.geompyD, m) for m in aSmeshMeshes ]
         return aMeshes, aStatus
 
-    ## Creates a Mesh object importing data from the given GMF file.
+    ## Create a Mesh object importing data from the given GMF file.
     #  GMF files must have .mesh extension for the ASCII format and .meshb for
     #  the binary format.
     #  @return [ an instance of Mesh class, SMESH.ComputeError ]
@@ -608,7 +613,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @param allGroups forces creation of groups corresponding to every input mesh
     #  @param name name of a new mesh
     #  @return an instance of Mesh class
-    #  @ingroup l2_compounds
+    #  @ingroup l1_creating
     def Concatenate( self, meshes, uniteIdenticalGroups,
                      mergeNodesAndElements = False, mergeTolerance = 1e-5, allGroups = False,
                      name = ""):
@@ -635,29 +640,30 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     #  @param toCopyGroups to create in the new mesh groups the copied elements belongs to
     #  @param toKeepIDs to preserve order of the copied elements or not
     #  @return an instance of Mesh class
+    #  @ingroup l1_creating
     def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False):
         if (isinstance( meshPart, Mesh )):
             meshPart = meshPart.GetMesh()
         mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs )
         return Mesh(self, self.geompyD, mesh)
 
-    ## From SMESH_Gen interface
+    ## Return IDs of sub-shapes
     #  @return the list of integer values
     #  @ingroup l1_auxiliary
     def GetSubShapesId( self, theMainObject, theListOfSubObjects ):
         return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects)
 
-    ## From SMESH_Gen interface. Creates a pattern
+    ## Create a pattern mapper. 
     #  @return an instance of SMESH_Pattern
     #
     #  <a href="../tui_modifying_meshes_page.html#tui_pattern_mapping">Example of Patterns usage</a>
-    #  @ingroup l2_modif_patterns
+    #  @ingroup l1_modifying
     def GetPattern(self):
         return SMESH._objref_SMESH_Gen.GetPattern(self)
 
-    ## Sets number of segments per diagonal of boundary box of geometry by which
-    #  default segment length of appropriate 1D hypotheses is defined.
-    #  Default value is 10
+    ## Set number of segments per diagonal of boundary box of geometry, by which
+    #  default segment length of appropriate 1D hypotheses is defined in GUI.
+    #  Default value is 10.
     #  @ingroup l1_auxiliary
     def SetBoundaryBoxSegmentation(self, nbSegments):
         SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments)
@@ -665,7 +671,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
     # Filtering. Auxiliary functions:
     # ------------------------------
 
-    ## Creates an empty criterion
+    ## Create an empty criterion
     #  @return SMESH.Filter.Criterion
     #  @ingroup l1_controls
     def GetEmptyCriterion(self):
@@ -682,7 +688,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         return Filter.Criterion(Type, Compare, Threshold, ThresholdStr, ThresholdID,
                                 UnaryOp, BinaryOp, Tolerance, TypeOfElement, Precision)
 
-    ## Creates a criterion by the given parameters
+    ## Create a criterion by the given parameters
     #  \n Criterion structures allow to define complex filters by combining them with logical operations (AND / OR) (see example below)
     #  @param elementType the type of elements(SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
     #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
@@ -870,7 +876,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
         return aCriterion
 
-    ## Creates a filter with the given parameters
+    ## Create a filter with the given parameters
     #  @param elementType the type of elements (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
     #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
     #          Type SMESH.FunctorType._items in the Python Console to see all values.
@@ -904,7 +910,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aFilterMgr.UnRegister()
         return aFilter
 
-    ## Creates a filter from criteria
+    ## Create a filter from criteria
     #  @param criteria a list of criteria
     #  @param binOp binary operator used when binary operator of criteria is undefined
     #  @return SMESH_Filter
@@ -921,7 +927,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aFilterMgr.UnRegister()
         return aFilter
 
-    ## Creates a numerical functor by its type
+    ## Create a numerical functor by its type
     #  @param theCriterion functor type - an item of SMESH.FunctorType enumeration.
     #          Type SMESH.FunctorType._items in the Python Console to see all items.
     #          Note that not all items correspond to numerical functors.
@@ -969,7 +975,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
         aFilterMgr.UnRegister()
         return functor
 
-    ## Creates hypothesis
+    ## Create hypothesis
     #  @param theHType mesh hypothesis type (string)
     #  @param theLibName mesh plug-in library name
     #  @return created hypothesis instance
@@ -990,7 +996,7 @@ class smeshBuilder(object, SMESH._objref_SMESH_Gen):
 
         return hyp
 
-    ## Gets the mesh statistic
+    ## Get the mesh statistic
     #  @return dictionary "element type" - "count of elements"
     #  @ingroup l1_meshinfo
     def GetMeshInfo(self, obj):
@@ -1203,7 +1209,7 @@ def New( study, instance=None):
 #  It has a set of methods to build a mesh on the given geometry, including the definition of sub-meshes.
 #  It also has methods to define groups of mesh elements, to modify a mesh (by addition of
 #  new nodes and elements and by changing the existing entities), to get information
-#  about a mesh and to export a mesh into different formats.
+#  about a mesh and to export a mesh in different formats.
 class Mesh:
     __metaclass__ = MeshMeta
 
@@ -1213,7 +1219,7 @@ class Mesh:
 
     ## Constructor
     #
-    #  Creates a mesh on the shape \a obj (or an empty mesh if \a obj is equal to 0) and
+    #  Create a mesh on the shape \a obj (or an empty mesh if \a obj is equal to 0) and
     #  sets the GUI name of this mesh to \a name.
     #  @param smeshpyD an instance of smeshBuilder class
     #  @param geompyD an instance of geomBuilder class
@@ -1275,7 +1281,7 @@ class Mesh:
             pass
         pass
         
-    ## Initializes the Mesh object from an instance of SMESH_Mesh interface
+    ## Initialize the Mesh object from an instance of SMESH_Mesh interface
     #  @param theMesh a SMESH_Mesh object
     #  @ingroup l2_construct
     def SetMesh(self, theMesh):
@@ -1287,60 +1293,76 @@ class Mesh:
             self.geom = self.mesh.GetShapeToMesh()
         pass
 
-    ## Returns the mesh, that is an instance of SMESH_Mesh interface
+    ## Return the mesh, that is an instance of SMESH_Mesh interface
     #  @return a SMESH_Mesh object
     #  @ingroup l2_construct
     def GetMesh(self):
         return self.mesh
 
-    ## Gets the name of the mesh
+    ## Get the name of the mesh
     #  @return the name of the mesh as a string
     #  @ingroup l2_construct
     def GetName(self):
         name = GetName(self.GetMesh())
         return name
 
-    ## Sets a name to the mesh
+    ## Set a name to the mesh
     #  @param name a new name of the mesh
     #  @ingroup l2_construct
     def SetName(self, name):
         self.smeshpyD.SetName(self.GetMesh(), name)
 
-    ## Gets the subMesh object associated to a \a theSubObject geometrical object.
-    #  The subMesh object gives access to the IDs of nodes and elements.
+    ## Get a sub-mesh object associated to a \a geom geometrical object.
     #  @param geom a geometrical object (shape)
-    #  @param name a name for the submesh
-    #  @return an object of type SMESH_SubMesh, representing a part of mesh, which lies on the given shape
+    #  @param name a name for the sub-mesh in the Object Browser
+    #  @return an object of type SMESH.SMESH_subMesh, representing a part of mesh,
+    #          which lies on the given shape
+    #
+    #  The sub-mesh object gives access to the IDs of nodes and elements.
+    #  The sub-mesh object has the following methods:
+    #  - SMESH.SMESH_subMesh.GetNumberOfElements()
+    #  - SMESH.SMESH_subMesh.GetNumberOfNodes( all )
+    #  - SMESH.SMESH_subMesh.GetElementsId()
+    #  - SMESH.SMESH_subMesh.GetElementsByType( ElementType )
+    #  - SMESH.SMESH_subMesh.GetNodesId()
+    #  - SMESH.SMESH_subMesh.GetSubShape()
+    #  - SMESH.SMESH_subMesh.GetFather()
+    #  - SMESH.SMESH_subMesh.GetId()
+    #  @note A sub-mesh is implicitly created when a sub-shape is specified at
+    #  creating an algorithm, for example: <code>algo1D = mesh.Segment(geom=Edge_1) </code>
+    #  creates a sub-mesh on @c Edge_1 and assign Wire Discretization algorithm to it.
+    #  The created sub-mesh can be retrieved from the algorithm:
+    #  <code>submesh = algo1D.GetSubMesh()</code>
     #  @ingroup l2_submeshes
     def GetSubMesh(self, geom, name):
         AssureGeomPublished( self, geom, name )
         submesh = self.mesh.GetSubMesh( geom, name )
         return submesh
 
-    ## Returns the shape associated to the mesh
+    ## Return the shape associated to the mesh
     #  @return a GEOM_Object
     #  @ingroup l2_construct
     def GetShape(self):
         return self.geom
 
-    ## Associates the given shape to the mesh (entails the recreation of the mesh)
+    ## Associate the given shape to the mesh (entails the recreation of the mesh)
     #  @param geom the shape to be meshed (GEOM_Object)
     #  @ingroup l2_construct
     def SetShape(self, geom):
         self.mesh = self.smeshpyD.CreateMesh(geom)
 
-    ## Loads mesh from the study after opening the study
+    ## Load mesh from the study after opening the study
     def Load(self):
         self.mesh.Load()
 
-    ## Returns true if the hypotheses are defined well
+    ## Return true if the hypotheses are defined well
     #  @param theSubObject a sub-shape of a mesh shape
     #  @return True or False
     #  @ingroup l2_construct
     def IsReadyToCompute(self, theSubObject):
         return self.smeshpyD.IsReadyToCompute(self.mesh, theSubObject)
 
-    ## Returns errors of hypotheses definition.
+    ## Return errors of hypotheses definition.
     #  The list of errors is empty if everything is OK.
     #  @param theSubObject a sub-shape of a mesh shape
     #  @return a list of errors
@@ -1348,20 +1370,20 @@ class Mesh:
     def GetAlgoState(self, theSubObject):
         return self.smeshpyD.GetAlgoState(self.mesh, theSubObject)
 
-    ## Returns a geometrical object on which the given element was built.
+    ## Return a geometrical object on which the given element was built.
     #  The returned geometrical object, if not nil, is either found in the
     #  study or published by this method with the given name
     #  @param theElementID the id of the mesh element
     #  @param theGeomName the user-defined name of the geometrical object
     #  @return GEOM::GEOM_Object instance
-    #  @ingroup l2_construct
+    #  @ingroup l1_meshinfo
     def GetGeometryByMeshElement(self, theElementID, theGeomName):
         return self.smeshpyD.GetGeometryByMeshElement( self.mesh, theElementID, theGeomName )
 
-    ## Returns the mesh dimension depending on the dimension of the underlying shape
+    ## Return the mesh dimension depending on the dimension of the underlying shape
     #  or, if the mesh is not based on any shape, basing on deimension of elements
     #  @return mesh dimension as an integer value [0,3]
-    #  @ingroup l1_auxiliary
+    #  @ingroup l1_meshinfo
     def MeshDimension(self):
         if self.mesh.HasShapeToMesh():
             shells = self.geompyD.SubShapeAllIDs( self.geom, self.geompyD.ShapeType["SOLID"] )
@@ -1379,10 +1401,11 @@ class Mesh:
             if self.NbEdges()   > 0: return 1
         return 0
 
-    ## Evaluates size of prospective mesh on a shape
+    ## Evaluate size of prospective mesh on a shape
     #  @return a list where i-th element is a number of elements of i-th SMESH.EntityType
     #  To know predicted number of e.g. edges, inquire it this way
     #  Evaluate()[ EnumToLong( Entity_Edge )]
+    #  @ingroup l2_construct
     def Evaluate(self, geom=0):
         if geom == 0 or not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
             if self.geom == 0:
@@ -1392,7 +1415,7 @@ class Mesh:
         return self.smeshpyD.Evaluate(self.mesh, geom)
 
 
-    ## Computes the mesh and returns the status of the computation
+    ## Compute the mesh and return the status of the computation
     #  @param geom geomtrical shape on which mesh data should be computed
     #  @param discardModifs if True and the mesh has been edited since
     #         a last total re-compute and that may prevent successful partial re-compute,
@@ -1446,7 +1469,7 @@ class Mesh:
                     errText = "code %s" % -err.code
                 if errText: errText += ". "
                 errText += err.comment
-                if allReasons != "":allReasons += "\n"
+                if allReasonsallReasons += "\n"
                 if ok:
                     allReasons += '-  "%s"%s - %s' %(err.algoName, shapeText, errText)
                 else:
@@ -1484,7 +1507,7 @@ class Mesh:
                     reason = ("For unknown reason. "
                               "Developer, revise Mesh.Compute() implementation in smeshBuilder.py!")
                     pass
-                if allReasons != "":allReasons += "\n"
+                if allReasonsallReasons += "\n"
                 allReasons += "-  " + reason
                 pass
             if not ok or allReasons != "":
@@ -1506,6 +1529,7 @@ class Mesh:
         return ok
 
     ## Return a list of error messages (SMESH.ComputeError) of the last Compute()
+    #  @ingroup l2_construct
     def GetComputeErrors(self, shape=0 ):
         if shape == 0:
             shape = self.mesh.GetShapeToMesh()
@@ -1518,6 +1542,7 @@ class Mesh:
     #  - FACE #3      (not published sub-shape)
     #  - sub-shape #3 (invalid sub-shape ID)
     #  - #3           (error in this function)
+    #  @ingroup l1_auxiliary
     def GetSubShapeName(self, subShapeID ):
         if not self.mesh.HasShapeToMesh():
             return ""
@@ -1560,6 +1585,7 @@ class Mesh:
     #  error of an algorithm
     #  @param publish if @c True, the returned groups will be published in the study
     #  @return a list of GEOM groups each named after a failed algorithm
+    #  @ingroup l2_construct
     def GetFailedShapes(self, publish=False):
 
         algo2shapes = {}
@@ -1604,13 +1630,13 @@ class Mesh:
     def GetMeshOrder(self):
         return self.mesh.GetMeshOrder()
 
-    ## Set order in which concurrent sub-meshes sould be meshed
+    ## Set order in which concurrent sub-meshes should be meshed
     #  @param submeshes list of lists of sub-meshes
     #  @ingroup l2_construct
     def SetMeshOrder(self, submeshes):
         return self.mesh.SetMeshOrder(submeshes)
 
-    ## Removes all nodes and elements
+    ## Remove all nodes and elements generated on geometry. Imported elements remain.
     #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
     #  @ingroup l2_construct
     def Clear(self, refresh=False):
@@ -1622,10 +1648,10 @@ class Mesh:
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             if refresh: salome.sg.updateObjBrowser(True)
 
-    ## Removes all nodes and elements of indicated shape
+    ## Remove all nodes and elements of indicated shape
     #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
     #  @param geomId the ID of a sub-shape to remove elements on
-    #  @ingroup l2_construct
+    #  @ingroup l2_submeshes
     def ClearSubMesh(self, geomId, refresh=False):
         self.mesh.ClearSubMesh(geomId)
         if salome.sg.hasDesktop():
@@ -1634,7 +1660,7 @@ class Mesh:
             smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), False, True )
             if refresh: salome.sg.updateObjBrowser(True)
 
-    ## Computes a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
+    ## Compute a tetrahedral mesh using AutomaticLength + MEFISTO + Tetrahedron
     #  @param fineness [0.0,1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
@@ -1651,7 +1677,7 @@ class Mesh:
             pass
         return self.Compute()
 
-    ## Computes an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
+    ## Compute an hexahedral mesh using AutomaticLength + Quadrangle + Hexahedron
     #  @param fineness [0.0, 1.0] defines mesh fineness
     #  @return True or False
     #  @ingroup l3_algos_basic
@@ -1668,11 +1694,11 @@ class Mesh:
             pass
         return self.Compute()
 
-    ## Assigns a hypothesis
+    ## Assign a hypothesis
     #  @param hyp a hypothesis to assign
     #  @param geom a subhape of mesh geometry
     #  @return SMESH.Hypothesis_Status
-    #  @ingroup l2_hypotheses
+    #  @ingroup l2_editing
     def AddHypothesis(self, hyp, geom=0):
         if isinstance( hyp, geomBuilder.GEOM._objref_GEOM_Object ):
             hyp, geom = geom, hyp
@@ -1710,7 +1736,7 @@ class Mesh:
     #  @param hyp a hypothesis to check
     #  @param geom a subhape of mesh geometry
     #  @return True of False
-    #  @ingroup l2_hypotheses
+    #  @ingroup l2_editing
     def IsUsedHypothesis(self, hyp, geom):
         if not hyp: # or not geom
             return False
@@ -1723,11 +1749,11 @@ class Mesh:
                 return True
         return False
 
-    ## Unassigns a hypothesis
+    ## Unassign a hypothesis
     #  @param hyp a hypothesis to unassign
     #  @param geom a sub-shape of mesh geometry
     #  @return SMESH.Hypothesis_Status
-    #  @ingroup l2_hypotheses
+    #  @ingroup l2_editing
     def RemoveHypothesis(self, hyp, geom=0):
         if not hyp:
             return None
@@ -1745,15 +1771,15 @@ class Mesh:
         print "WARNING: RemoveHypothesis() failed as '%s' is not assigned to '%s' shape" % ( hypName, geoName )
         return None
 
-    ## Gets the list of hypotheses added on a geometry
+    ## Get the list of hypotheses added on a geometry
     #  @param geom a sub-shape of mesh geometry
     #  @return the sequence of SMESH_Hypothesis
-    #  @ingroup l2_hypotheses
+    #  @ingroup l2_editing
     def GetHypothesisList(self, geom):
         return self.mesh.GetHypothesisList( geom )
 
-    ## Removes all global hypotheses
-    #  @ingroup l2_hypotheses
+    ## Remove all global hypotheses
+    #  @ingroup l2_editing
     def RemoveGlobalHypotheses(self):
         current_hyps = self.mesh.GetHypothesisList( self.geom )
         for hyp in current_hyps:
@@ -1761,27 +1787,29 @@ class Mesh:
             pass
         pass
 
-   ## Exports the mesh in a file in MED format and chooses the \a version of MED format
+    ## Export the mesh in a file in MED format
     ## allowing to overwrite the file if it exists or add the exported data to its contents
     #  @param f is the file name
     #  @param auto_groups boolean parameter for creating/not creating
     #  the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
-    #  the typical use is auto_groups=false.
-    #  @param version MED format version(MED_V2_1 or MED_V2_2)
+    #  the typical use is auto_groups=False.
+    #  @param version MED format version (MED_V2_1 or MED_V2_2,
+    #                 the latter meaning any current version). The parameter is
+    #                 obsolete since MED_V2_1 is no longer supported.
     #  @param overwrite boolean parameter for overwriting/not overwriting the file
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
-    #  @param autoDimension: if @c True (default), a space dimension of a MED mesh can be either
+    #  @param autoDimension if @c True (default), a space dimension of a MED mesh can be either
     #         - 1D if all mesh nodes lie on OX coordinate axis, or
     #         - 2D if all mesh nodes lie on XOY coordinate plane, or
-    #         - 3D in the rest cases.
+    #         - 3D in the rest cases.<br>
     #         If @a autoDimension is @c False, the space dimension is always 3.
-    #  @param fields list of GEOM fields defined on the shape to mesh.
-    #  @param geomAssocFields each character of this string means a need to export a 
+    #  @param fields list of GEOM fields defined on the shape to mesh.
+    #  @param geomAssocFields each character of this string means a need to export a 
     #         corresponding field; correspondence between fields and characters is following:
-    #         - 'v' stands for _vertices_ field;
-    #         - 'e' stands for _edges_ field;
-    #         - 'f' stands for _faces_ field;
-    #         - 's' stands for _solids_ field.
+    #         - 'v' stands for "_vertices _" field;
+    #         - 'e' stands for "_edges _" field;
+    #         - 'f' stands for "_faces _" field;
+    #         - 's' stands for "_solids _" field.
     #  @ingroup l2_impexp
     def ExportMED(self, f, auto_groups=0, version=MED_V2_2,
                   overwrite=1, meshPart=None, autoDimension=True, fields=[], geomAssocFields=''):
@@ -1795,7 +1823,7 @@ class Mesh:
         else:
             self.mesh.ExportToMEDX(f, auto_groups, version, overwrite, autoDimension)
 
-    ## Exports the mesh in a file in SAUV format
+    ## Export the mesh in a file in SAUV format
     #  @param f is the file name
     #  @param auto_groups boolean parameter for creating/not creating
     #  the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
@@ -1804,7 +1832,7 @@ class Mesh:
     def ExportSAUV(self, f, auto_groups=0):
         self.mesh.ExportSAUV(f, auto_groups)
 
-    ## Exports the mesh in a file in DAT format
+    ## Export the mesh in a file in DAT format
     #  @param f the file name
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
     #  @ingroup l2_impexp
@@ -1818,7 +1846,7 @@ class Mesh:
         else:
             self.mesh.ExportDAT(f)
 
-    ## Exports the mesh in a file in UNV format
+    ## Export the mesh in a file in UNV format
     #  @param f the file name
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
     #  @ingroup l2_impexp
@@ -1847,12 +1875,15 @@ class Mesh:
         else:
             self.mesh.ExportSTL(f, ascii)
 
-    ## Exports the mesh in a file in CGNS format
+    ## Export the mesh in a file in CGNS format
     #  @param f is the file name
     #  @param overwrite boolean parameter for overwriting/not overwriting the file
     #  @param meshPart a part of mesh (group, sub-mesh) to export instead of the mesh
+    #  @param groupElemsByType if true all elements of same entity type are exported at ones,
+    #         else elements are exported in order of their IDs which can cause creation
+    #         of multiple cgns sections
     #  @ingroup l2_impexp
-    def ExportCGNS(self, f, overwrite=1, meshPart=None):
+    def ExportCGNS(self, f, overwrite=1, meshPart=None, groupElemsByType=False):
         unRegister = genObjUnRegister()
         if isinstance( meshPart, list ):
             meshPart = self.GetIDSource( meshPart, SMESH.ALL )
@@ -1861,9 +1892,9 @@ class Mesh:
             meshPart = meshPart.mesh
         elif not meshPart:
             meshPart = self.mesh
-        self.mesh.ExportCGNS(meshPart, f, overwrite)
+        self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
 
-    ## Exports the mesh in a file in GMF format.
+    ## Export the mesh in a file in GMF format.
     #  GMF files must have .mesh extension for the ASCII format and .meshb for
     #  the bynary format. Other extensions are not allowed.
     #  @param f is the file name
@@ -1880,28 +1911,29 @@ class Mesh:
             meshPart = self.mesh
         self.mesh.ExportGMF(meshPart, f, True)
 
-    ## Deprecated, used only for compatibility! Please, use ExportToMEDX() method instead.
-    #  Exports the mesh in a file in MED format and chooses the \a version of MED format
-    ## allowing to overwrite the file if it exists or add the exported data to its contents
+    ## Deprecated, used only for compatibility! Please, use ExportMED() method instead.
+    #  Export the mesh in a file in MED format
+    #  allowing to overwrite the file if it exists or add the exported data to its contents
     #  @param f the file name
-    #  @param version values are SMESH.MED_V2_1, SMESH.MED_V2_2
+    #  @param version MED format version (MED_V2_1 or MED_V2_2,
+    #                 the latter meaning any current version). The parameter is
+    #                 obsolete since MED_V2_1 is no longer supported.
     #  @param opt boolean parameter for creating/not creating
     #         the groups Group_On_All_Nodes, Group_On_All_Faces, ...
     #  @param overwrite boolean parameter for overwriting/not overwriting the file
-    #  @param autoDimension: if @c True (default), a space dimension of a MED mesh can be either
+    #  @param autoDimension if @c True (default), a space dimension of a MED mesh can be either
     #         - 1D if all mesh nodes lie on OX coordinate axis, or
     #         - 2D if all mesh nodes lie on XOY coordinate plane, or
-    #         - 3D in the rest cases.
-    #
+    #         - 3D in the rest cases.<br>
     #         If @a autoDimension is @c False, the space dimension is always 3.
     #  @ingroup l2_impexp
-    def ExportToMED(self, f, version, opt=0, overwrite=1, autoDimension=True):
+    def ExportToMED(self, f, version=MED_V2_2, opt=0, overwrite=1, autoDimension=True):
         self.mesh.ExportToMEDX(f, opt, version, overwrite, autoDimension)
 
     # Operations with groups:
     # ----------------------
 
-    ## Creates an empty mesh group
+    ## Create an empty mesh group
     #  @param elementType the type of elements in the group; either of 
     #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
     #  @param name the name of the mesh group
@@ -1910,7 +1942,7 @@ class Mesh:
     def CreateEmptyGroup(self, elementType, name):
         return self.mesh.CreateGroup(elementType, name)
 
-    ## Creates a mesh group based on the geometric object \a grp
+    ## Create a mesh group based on the geometric object \a grp
     #  and gives a \a name, \n if this parameter is not defined
     #  the name is the same as the geometric group name \n
     #  Note: Works like GroupOnGeom().
@@ -1921,7 +1953,7 @@ class Mesh:
     def Group(self, grp, name=""):
         return self.GroupOnGeom(grp, name)
 
-    ## Creates a mesh group based on the geometrical object \a grp
+    ## Create a mesh group based on the geometrical object \a grp
     #  and gives a \a name, \n if this parameter is not defined
     #  the name is the same as the geometrical group name
     #  @param grp  a geometrical group, a vertex, an edge, a face or a solid
@@ -1960,7 +1992,7 @@ class Mesh:
                   "_groupTypeFromShape(): invalid geometry '%s'" % GetName(shape)
         return typ
 
-    ## Creates a mesh group with given \a name based on the \a filter which
+    ## Create a mesh group with given \a name based on the \a filter which
     ## is a special type of group dynamically updating it's contents during
     ## mesh modification
     #  @param typ  the type of elements in the group; either of 
@@ -1972,7 +2004,7 @@ class Mesh:
     def GroupOnFilter(self, typ, name, filter):
         return self.mesh.CreateGroupFromFilter(typ, name, filter)
 
-    ## Creates a mesh group by the given ids of elements
+    ## Create a mesh group by the given ids of elements
     #  @param groupName the name of the mesh group
     #  @param elementType the type of elements in the group; either of 
     #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME).
@@ -1981,6 +2013,8 @@ class Mesh:
     #  @ingroup l2_grps_create
     def MakeGroupByIds(self, groupName, elementType, elemIDs):
         group = self.mesh.CreateGroup(elementType, groupName)
+        if isinstance( elemIDs, Mesh ):
+            elemIDs = elemIDs.GetMesh()
         if hasattr( elemIDs, "GetIDs" ):
             if hasattr( elemIDs, "SetMesh" ):
                 elemIDs.SetMesh( self.GetMesh() )
@@ -1989,7 +2023,7 @@ class Mesh:
             group.Add(elemIDs)
         return group
 
-    ## Creates a mesh group by the given conditions
+    ## Create a mesh group by the given conditions
     #  @param groupName the name of the mesh group
     #  @param elementType the type of elements(SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
     #  @param CritType the type of criterion (SMESH.FT_Taper, SMESH.FT_Area, etc.)
@@ -2014,7 +2048,7 @@ class Mesh:
         group = self.MakeGroupByCriterion(groupName, aCriterion)
         return group
 
-    ## Creates a mesh group by the given criterion
+    ## Create a mesh group by the given criterion
     #  @param groupName the name of the mesh group
     #  @param Criterion the instance of Criterion class
     #  @return SMESH_GroupOnFilter
@@ -2022,7 +2056,7 @@ class Mesh:
     def MakeGroupByCriterion(self, groupName, Criterion):
         return self.MakeGroupByCriteria( groupName, [Criterion] )
 
-    ## Creates a mesh group by the given criteria (list of criteria)
+    ## Create a mesh group by the given criteria (list of criteria)
     #  @param groupName the name of the mesh group
     #  @param theCriteria the list of criteria
     #  @param binOp binary operator used when binary operator of criteria is undefined
@@ -2033,7 +2067,7 @@ class Mesh:
         group = self.MakeGroupByFilter(groupName, aFilter)
         return group
 
-    ## Creates a mesh group by the given filter
+    ## Create a mesh group by the given filter
     #  @param groupName the name of the mesh group
     #  @param theFilter the instance of Filter class
     #  @return SMESH_GroupOnFilter
@@ -2045,17 +2079,17 @@ class Mesh:
         group = self.GroupOnFilter( theFilter.GetElementType(), groupName, theFilter )
         return group
 
-    ## Removes a group
+    ## Remove a group
     #  @ingroup l2_grps_delete
     def RemoveGroup(self, group):
         self.mesh.RemoveGroup(group)
 
-    ## Removes a group with its contents
+    ## Remove a group with its contents
     #  @ingroup l2_grps_delete
     def RemoveGroupWithContents(self, group):
         self.mesh.RemoveGroupWithContents(group)
 
-    ## Gets the list of groups existing in the mesh in the order
+    ## Get the list of groups existing in the mesh in the order
     #  of creation (starting from the oldest one)
     #  @param elemType type of elements the groups contain; either of 
     #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME);
@@ -2074,13 +2108,13 @@ class Mesh:
             pass
         return typedGroups
 
-    ## Gets the number of groups existing in the mesh
+    ## Get the number of groups existing in the mesh
     #  @return the quantity of groups as an integer value
     #  @ingroup l2_grps_create
     def NbGroups(self):
         return self.mesh.NbGroups()
 
-    ## Gets the list of names of groups existing in the mesh
+    ## Get the list of names of groups existing in the mesh
     #  @return list of strings
     #  @ingroup l2_grps_create
     def GetGroupNames(self):
@@ -2090,7 +2124,7 @@ class Mesh:
             names.append(group.GetName())
         return names
 
-    ## Finds groups by name and type
+    ## Find groups by name and type
     #  @param name name of the group of interest
     #  @param elemType type of elements the groups contain; either of 
     #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME);
@@ -2109,7 +2143,7 @@ class Mesh:
                     groups.append( group )
         return groups
 
-    ## Produces a union of two groups.
+    ## Produce a union of two groups.
     #  A new group is created. All mesh elements that are
     #  present in the initial groups are added to the new one
     #  @return an instance of SMESH_Group
@@ -2117,7 +2151,7 @@ class Mesh:
     def UnionGroups(self, group1, group2, name):
         return self.mesh.UnionGroups(group1, group2, name)
 
-    ## Produces a union list of groups.
+    ## Produce a union list of groups.
     #  New group is created. All mesh elements that are present in
     #  initial groups are added to the new one
     #  @return an instance of SMESH_Group
@@ -2125,7 +2159,7 @@ class Mesh:
     def UnionListOfGroups(self, groups, name):
       return self.mesh.UnionListOfGroups(groups, name)
 
-    ## Prodices an intersection of two groups.
+    ## Prodice an intersection of two groups.
     #  A new group is created. All mesh elements that are common
     #  for the two initial groups are added to the new one.
     #  @return an instance of SMESH_Group
@@ -2133,7 +2167,7 @@ class Mesh:
     def IntersectGroups(self, group1, group2, name):
         return self.mesh.IntersectGroups(group1, group2, name)
 
-    ## Produces an intersection of groups.
+    ## Produce an intersection of groups.
     #  New group is created. All mesh elements that are present in all
     #  initial groups simultaneously are added to the new one
     #  @return an instance of SMESH_Group
@@ -2141,7 +2175,7 @@ class Mesh:
     def IntersectListOfGroups(self, groups, name):
       return self.mesh.IntersectListOfGroups(groups, name)
 
-    ## Produces a cut of two groups.
+    ## Produce a cut of two groups.
     #  A new group is created. All mesh elements that are present in
     #  the main group but are not present in the tool group are added to the new one
     #  @return an instance of SMESH_Group
@@ -2149,7 +2183,7 @@ class Mesh:
     def CutGroups(self, main_group, tool_group, name):
         return self.mesh.CutGroups(main_group, tool_group, name)
 
-    ## Produces a cut of groups.
+    ## Produce a cut of groups.
     #  A new group is created. All mesh elements that are present in main groups
     #  but do not present in tool groups are added to the new one
     #  @return an instance of SMESH_Group
@@ -2185,14 +2219,14 @@ class Mesh:
 
 
     ## Convert group on geom into standalone group
-    #  @ingroup l2_grps_edit
+    #  @ingroup l2_grps_operon
     def ConvertToStandalone(self, group):
         return self.mesh.ConvertToStandalone(group)
 
     # Get some info about mesh:
     # ------------------------
 
-    ## Returns the log of nodes and elements added or removed
+    ## Return the log of nodes and elements added or removed
     #  since the previous clear of the log.
     #  @param clearAfterGet log is emptied after Get (safe if concurrents access)
     #  @return list of log_block structures:
@@ -2204,25 +2238,27 @@ class Mesh:
     def GetLog(self, clearAfterGet):
         return self.mesh.GetLog(clearAfterGet)
 
-    ## Clears the log of nodes and elements added or removed since the previous
+    ## Clear the log of nodes and elements added or removed since the previous
     #  clear. Must be used immediately after GetLog if clearAfterGet is false.
     #  @ingroup l1_auxiliary
     def ClearLog(self):
         self.mesh.ClearLog()
 
-    ## Toggles auto color mode on the object.
+    ## Toggle auto color mode on the object.
     #  @param theAutoColor the flag which toggles auto color mode.
-    #  @ingroup l1_auxiliary
+    #
+    #  If switched on, a default color of a new group in Create Group dialog is chosen randomly.
+    #  @ingroup l1_grouping
     def SetAutoColor(self, theAutoColor):
         self.mesh.SetAutoColor(theAutoColor)
 
-    ## Gets flag of object auto color mode.
+    ## Get flag of object auto color mode.
     #  @return True or False
-    #  @ingroup l1_auxiliary
+    #  @ingroup l1_grouping
     def GetAutoColor(self):
         return self.mesh.GetAutoColor()
 
-    ## Gets the internal ID
+    ## Get the internal ID
     #  @return integer value, which is the internal Id of the mesh
     #  @ingroup l1_auxiliary
     def GetId(self):
@@ -2234,14 +2270,14 @@ class Mesh:
     def GetStudyId(self):
         return self.mesh.GetStudyId()
 
-    ## Checks the group names for duplications.
+    ## Check the group names for duplications.
     #  Consider the maximum group name length stored in MED file.
     #  @return True or False
-    #  @ingroup l1_auxiliary
+    #  @ingroup l1_grouping
     def HasDuplicatedGroupNamesMED(self):
         return self.mesh.HasDuplicatedGroupNamesMED()
 
-    ## Obtains the mesh editor tool
+    ## Obtain the mesh editor tool
     #  @return an instance of SMESH_MeshEditor
     #  @ingroup l1_modifying
     def GetMeshEditor(self):
@@ -2268,44 +2304,44 @@ class Mesh:
     # Get informations about mesh contents:
     # ------------------------------------
 
-    ## Gets the mesh stattistic
+    ## Get the mesh stattistic
     #  @return dictionary type element - count of elements
     #  @ingroup l1_meshinfo
     def GetMeshInfo(self, obj = None):
         if not obj: obj = self.mesh
         return self.smeshpyD.GetMeshInfo(obj)
 
-    ## Returns the number of nodes in the mesh
+    ## Return the number of nodes in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbNodes(self):
         return self.mesh.NbNodes()
 
-    ## Returns the number of elements in the mesh
+    ## Return the number of elements in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbElements(self):
         return self.mesh.NbElements()
 
-    ## Returns the number of 0d elements in the mesh
+    ## Return the number of 0d elements in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def Nb0DElements(self):
         return self.mesh.Nb0DElements()
 
-    ## Returns the number of ball discrete elements in the mesh
+    ## Return the number of ball discrete elements in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbBalls(self):
         return self.mesh.NbBalls()
 
-    ## Returns the number of edges in the mesh
+    ## Return the number of edges in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbEdges(self):
         return self.mesh.NbEdges()
 
-    ## Returns the number of edges with the given order in the mesh
+    ## Return the number of edges with the given order in the mesh
     #  @param elementOrder the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2313,13 +2349,13 @@ class Mesh:
     def NbEdgesOfOrder(self, elementOrder):
         return self.mesh.NbEdgesOfOrder(elementOrder)
 
-    ## Returns the number of faces in the mesh
+    ## Return the number of faces in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbFaces(self):
         return self.mesh.NbFaces()
 
-    ## Returns the number of faces with the given order in the mesh
+    ## Return the number of faces with the given order in the mesh
     #  @param elementOrder the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2327,13 +2363,13 @@ class Mesh:
     def NbFacesOfOrder(self, elementOrder):
         return self.mesh.NbFacesOfOrder(elementOrder)
 
-    ## Returns the number of triangles in the mesh
+    ## Return the number of triangles in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbTriangles(self):
         return self.mesh.NbTriangles()
 
-    ## Returns the number of triangles with the given order in the mesh
+    ## Return the number of triangles with the given order in the mesh
     #  @param elementOrder is the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2341,19 +2377,19 @@ class Mesh:
     def NbTrianglesOfOrder(self, elementOrder):
         return self.mesh.NbTrianglesOfOrder(elementOrder)
 
-    ## Returns the number of biquadratic triangles in the mesh
+    ## Return the number of biquadratic triangles in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbBiQuadTriangles(self):
         return self.mesh.NbBiQuadTriangles()
 
-    ## Returns the number of quadrangles in the mesh
+    ## Return the number of quadrangles in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbQuadrangles(self):
         return self.mesh.NbQuadrangles()
 
-    ## Returns the number of quadrangles with the given order in the mesh
+    ## Return the number of quadrangles with the given order in the mesh
     #  @param elementOrder the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2361,13 +2397,13 @@ class Mesh:
     def NbQuadranglesOfOrder(self, elementOrder):
         return self.mesh.NbQuadranglesOfOrder(elementOrder)
 
-    ## Returns the number of biquadratic quadrangles in the mesh
+    ## Return the number of biquadratic quadrangles in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbBiQuadQuadrangles(self):
         return self.mesh.NbBiQuadQuadrangles()
 
-    ## Returns the number of polygons of given order in the mesh
+    ## Return the number of polygons of given order in the mesh
     #  @param elementOrder the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2375,13 +2411,13 @@ class Mesh:
     def NbPolygons(self, elementOrder = SMESH.ORDER_ANY):
         return self.mesh.NbPolygonsOfOrder(elementOrder)
 
-    ## Returns the number of volumes in the mesh
+    ## Return the number of volumes in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbVolumes(self):
         return self.mesh.NbVolumes()
 
-    ## Returns the number of volumes with the given order in the mesh
+    ## Return the number of volumes with the given order in the mesh
     #  @param elementOrder  the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2389,13 +2425,13 @@ class Mesh:
     def NbVolumesOfOrder(self, elementOrder):
         return self.mesh.NbVolumesOfOrder(elementOrder)
 
-    ## Returns the number of tetrahedrons in the mesh
+    ## Return the number of tetrahedrons in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbTetras(self):
         return self.mesh.NbTetras()
 
-    ## Returns the number of tetrahedrons with the given order in the mesh
+    ## Return the number of tetrahedrons with the given order in the mesh
     #  @param elementOrder  the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2403,13 +2439,13 @@ class Mesh:
     def NbTetrasOfOrder(self, elementOrder):
         return self.mesh.NbTetrasOfOrder(elementOrder)
 
-    ## Returns the number of hexahedrons in the mesh
+    ## Return the number of hexahedrons in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbHexas(self):
         return self.mesh.NbHexas()
 
-    ## Returns the number of hexahedrons with the given order in the mesh
+    ## Return the number of hexahedrons with the given order in the mesh
     #  @param elementOrder  the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2417,19 +2453,19 @@ class Mesh:
     def NbHexasOfOrder(self, elementOrder):
         return self.mesh.NbHexasOfOrder(elementOrder)
 
-    ## Returns the number of triquadratic hexahedrons in the mesh
+    ## Return the number of triquadratic hexahedrons in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbTriQuadraticHexas(self):
         return self.mesh.NbTriQuadraticHexas()
 
-    ## Returns the number of pyramids in the mesh
+    ## Return the number of pyramids in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbPyramids(self):
         return self.mesh.NbPyramids()
 
-    ## Returns the number of pyramids with the given order in the mesh
+    ## Return the number of pyramids with the given order in the mesh
     #  @param elementOrder  the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2437,13 +2473,13 @@ class Mesh:
     def NbPyramidsOfOrder(self, elementOrder):
         return self.mesh.NbPyramidsOfOrder(elementOrder)
 
-    ## Returns the number of prisms in the mesh
+    ## Return the number of prisms in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbPrisms(self):
         return self.mesh.NbPrisms()
 
-    ## Returns the number of prisms with the given order in the mesh
+    ## Return the number of prisms with the given order in the mesh
     #  @param elementOrder  the order of elements:
     #         SMESH.ORDER_ANY, SMESH.ORDER_LINEAR or SMESH.ORDER_QUADRATIC
     #  @return an integer value
@@ -2451,31 +2487,31 @@ class Mesh:
     def NbPrismsOfOrder(self, elementOrder):
         return self.mesh.NbPrismsOfOrder(elementOrder)
 
-    ## Returns the number of hexagonal prisms in the mesh
+    ## Return the number of hexagonal prisms in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbHexagonalPrisms(self):
         return self.mesh.NbHexagonalPrisms()
 
-    ## Returns the number of polyhedrons in the mesh
+    ## Return the number of polyhedrons in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbPolyhedrons(self):
         return self.mesh.NbPolyhedrons()
 
-    ## Returns the number of submeshes in the mesh
+    ## Return the number of submeshes in the mesh
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def NbSubMesh(self):
         return self.mesh.NbSubMesh()
 
-    ## Returns the list of mesh elements IDs
+    ## Return the list of mesh elements IDs
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetElementsId(self):
         return self.mesh.GetElementsId()
 
-    ## Returns the list of IDs of mesh elements with the given type
+    ## Return the list of IDs of mesh elements with the given type
     #  @param elementType  the required type of elements, either of
     #         (SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
     #  @return list of integer values
@@ -2483,7 +2519,7 @@ class Mesh:
     def GetElementsByType(self, elementType):
         return self.mesh.GetElementsByType(elementType)
 
-    ## Returns the list of mesh nodes IDs
+    ## Return the list of mesh nodes IDs
     #  @return the list of integer values
     #  @ingroup l1_meshinfo
     def GetNodesId(self):
@@ -2492,28 +2528,28 @@ class Mesh:
     # Get the information about mesh elements:
     # ------------------------------------
 
-    ## Returns the type of mesh element
+    ## Return the type of mesh element
     #  @return the value from SMESH::ElementType enumeration
     #          Type SMESH.ElementType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
     def GetElementType(self, id, iselem=True):
         return self.mesh.GetElementType(id, iselem)
 
-    ## Returns the geometric type of mesh element
+    ## Return the geometric type of mesh element
     #  @return the value from SMESH::EntityType enumeration
     #          Type SMESH.EntityType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
     def GetElementGeomType(self, id):
         return self.mesh.GetElementGeomType(id)
 
-    ## Returns the shape type of mesh element
+    ## Return the shape type of mesh element
     #  @return the value from SMESH::GeometryType enumeration.
     #          Type SMESH.GeometryType._items in the Python Console to see all possible values.
     #  @ingroup l1_meshinfo
     def GetElementShape(self, id):
         return self.mesh.GetElementShape(id)
 
-    ## Returns the list of submesh elements IDs
+    ## Return the list of submesh elements IDs
     #  @param Shape a geom object(sub-shape)
     #         Shape must be the sub-shape of a ShapeToMesh()
     #  @return the list of integer values
@@ -2525,7 +2561,7 @@ class Mesh:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementsId(ShapeID)
 
-    ## Returns the list of submesh nodes IDs
+    ## Return the list of submesh nodes IDs
     #  @param Shape a geom object(sub-shape)
     #         Shape must be the sub-shape of a ShapeToMesh()
     #  @param all If true, gives all nodes of submesh elements, otherwise gives only submesh nodes
@@ -2538,7 +2574,7 @@ class Mesh:
             ShapeID = Shape
         return self.mesh.GetSubMeshNodesId(ShapeID, all)
 
-    ## Returns type of elements on given shape
+    ## Return type of elements on given shape
     #  @param Shape a geom object(sub-shape)
     #         Shape must be a sub-shape of a ShapeToMesh()
     #  @return element type
@@ -2550,7 +2586,7 @@ class Mesh:
             ShapeID = Shape
         return self.mesh.GetSubMeshElementType(ShapeID)
 
-    ## Gets the mesh description
+    ## Get the mesh description
     #  @return string value
     #  @ingroup l1_meshinfo
     def Dump(self):
@@ -2560,72 +2596,72 @@ class Mesh:
     # Get the information about nodes and elements of a mesh by its IDs:
     # -----------------------------------------------------------
 
-    ## Gets XYZ coordinates of a node
-    #  \n If there is no nodes for the given ID - returns an empty list
+    ## Get XYZ coordinates of a node
+    #  \n If there is no nodes for the given ID - return an empty list
     #  @return a list of double precision values
     #  @ingroup l1_meshinfo
     def GetNodeXYZ(self, id):
         return self.mesh.GetNodeXYZ(id)
 
-    ## Returns list of IDs of inverse elements for the given node
-    #  \n If there is no node for the given ID - returns an empty list
+    ## Return list of IDs of inverse elements for the given node
+    #  \n If there is no node for the given ID - return an empty list
     #  @return a list of integer values
     #  @ingroup l1_meshinfo
     def GetNodeInverseElements(self, id):
         return self.mesh.GetNodeInverseElements(id)
 
-    ## @brief Returns the position of a node on the shape
+    ## Return the position of a node on the shape
     #  @return SMESH::NodePosition
     #  @ingroup l1_meshinfo
     def GetNodePosition(self,NodeID):
         return self.mesh.GetNodePosition(NodeID)
 
-    ## @brief Returns the position of an element on the shape
+    ## Return the position of an element on the shape
     #  @return SMESH::ElementPosition
     #  @ingroup l1_meshinfo
     def GetElementPosition(self,ElemID):
         return self.mesh.GetElementPosition(ElemID)
 
-    ## Returns the ID of the shape, on which the given node was generated.
+    ## Return the ID of the shape, on which the given node was generated.
     #  @return an integer value > 0 or -1 if there is no node for the given
     #          ID or the node is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeID(self, id):
         return self.mesh.GetShapeID(id)
 
-    ## Returns the ID of the shape, on which the given element was generated.
+    ## Return the ID of the shape, on which the given element was generated.
     #  @return an integer value > 0 or -1 if there is no element for the given
     #          ID or the element is not assigned to any geometry
     #  @ingroup l1_meshinfo
     def GetShapeIDForElem(self,id):
         return self.mesh.GetShapeIDForElem(id)
 
-    ## Returns the number of nodes of the given element
+    ## Return the number of nodes of the given element
     #  @return an integer value > 0 or -1 if there is no element for the given ID
     #  @ingroup l1_meshinfo
     def GetElemNbNodes(self, id):
         return self.mesh.GetElemNbNodes(id)
 
-    ## Returns the node ID the given (zero based) index for the given element
-    #  \n If there is no element for the given ID - returns -1
-    #  \n If there is no node for the given index - returns -2
+    ## Return the node ID the given (zero based) index for the given element
+    #  \n If there is no element for the given ID - return -1
+    #  \n If there is no node for the given index - return -2
     #  @return an integer value
     #  @ingroup l1_meshinfo
     def GetElemNode(self, id, index):
         return self.mesh.GetElemNode(id, index)
 
-    ## Returns the IDs of nodes of the given element
+    ## Return the IDs of nodes of the given element
     #  @return a list of integer values
     #  @ingroup l1_meshinfo
     def GetElemNodes(self, id):
         return self.mesh.GetElemNodes(id)
 
-    ## Returns true if the given node is the medium node in the given quadratic element
+    ## Return true if the given node is the medium node in the given quadratic element
     #  @ingroup l1_meshinfo
     def IsMediumNode(self, elementID, nodeID):
         return self.mesh.IsMediumNode(elementID, nodeID)
 
-    ## Returns true if the given node is the medium node in one of quadratic elements
+    ## Return true if the given node is the medium node in one of quadratic elements
     #  @param nodeID ID of the node
     #  @param elementType  the type of elements to check a state of the node, either of
     #         (SMESH.ALL, SMESH.NODE, SMESH.EDGE, SMESH.FACE or SMESH.VOLUME)
@@ -2633,55 +2669,60 @@ class Mesh:
     def IsMediumNodeOfAnyElem(self, nodeID, elementType = SMESH.ALL ):
         return self.mesh.IsMediumNodeOfAnyElem(nodeID, elementType)
 
-    ## Returns the number of edges for the given element
+    ## Return the number of edges for the given element
     #  @ingroup l1_meshinfo
     def ElemNbEdges(self, id):
         return self.mesh.ElemNbEdges(id)
 
-    ## Returns the number of faces for the given element
+    ## Return the number of faces for the given element
     #  @ingroup l1_meshinfo
     def ElemNbFaces(self, id):
         return self.mesh.ElemNbFaces(id)
 
-    ## Returns nodes of given face (counted from zero) for given volumic element.
+    ## Return nodes of given face (counted from zero) for given volumic element.
     #  @ingroup l1_meshinfo
     def GetElemFaceNodes(self,elemId, faceIndex):
         return self.mesh.GetElemFaceNodes(elemId, faceIndex)
 
-    ## Returns three components of normal of given mesh face
+    ## Return three components of normal of given mesh face
     #  (or an empty array in KO case)
     #  @ingroup l1_meshinfo
     def GetFaceNormal(self, faceId, normalized=False):
         return self.mesh.GetFaceNormal(faceId,normalized)
 
-    ## Returns an element based on all given nodes.
+    ## Return an element based on all given nodes.
     #  @ingroup l1_meshinfo
-    def FindElementByNodes(self,nodes):
+    def FindElementByNodes(self, nodes):
         return self.mesh.FindElementByNodes(nodes)
 
-    ## Returns true if the given element is a polygon
+    ## Return elements including all given nodes.
+    #  @ingroup l1_meshinfo
+    def GetElementsByNodes(self, nodes, elemType=SMESH.ALL):
+        return self.mesh.GetElementsByNodes( nodes, elemType )
+
+    ## Return true if the given element is a polygon
     #  @ingroup l1_meshinfo
     def IsPoly(self, id):
         return self.mesh.IsPoly(id)
 
-    ## Returns true if the given element is quadratic
+    ## Return true if the given element is quadratic
     #  @ingroup l1_meshinfo
     def IsQuadratic(self, id):
         return self.mesh.IsQuadratic(id)
 
-    ## Returns diameter of a ball discrete element or zero in case of an invalid \a id
+    ## Return diameter of a ball discrete element or zero in case of an invalid \a id
     #  @ingroup l1_meshinfo
     def GetBallDiameter(self, id):
         return self.mesh.GetBallDiameter(id)
 
-    ## Returns XYZ coordinates of the barycenter of the given element
-    #  \n If there is no element for the given ID - returns an empty list
+    ## Return XYZ coordinates of the barycenter of the given element
+    #  \n If there is no element for the given ID - return an empty list
     #  @return a list of three double values
     #  @ingroup l1_meshinfo
     def BaryCenter(self, id):
         return self.mesh.BaryCenter(id)
 
-    ## Passes mesh elements through the given filter and return IDs of fitting elements
+    ## Pass mesh elements through the given filter and return IDs of fitting elements
     #  @param theFilter SMESH_Filter
     #  @return a list of ids
     #  @ingroup l1_controls
@@ -2689,10 +2730,13 @@ class Mesh:
         theFilter.SetMesh( self.mesh )
         return theFilter.GetIDs()
 
-    ## Verifies whether a 2D mesh element has free edges (edges connected to one face only)\n
-    #  Returns a list of special structures (borders).
+    # Get mesh measurements information:
+    # ------------------------------------
+
+    ## Verify whether a 2D mesh element has free edges (edges connected to one face only)\n
+    #  Return a list of special structures (borders).
     #  @return a list of SMESH.FreeEdges.Border structure: edge id and ids of two its nodes.
-    #  @ingroup l1_controls
+    #  @ingroup l1_measurements
     def GetFreeBorders(self):
         aFilterMgr = self.smeshpyD.CreateFilterManager()
         aPredicate = aFilterMgr.CreateFreeEdges()
@@ -2701,10 +2745,6 @@ class Mesh:
         aFilterMgr.UnRegister()
         return aBorders
 
-
-    # Get mesh measurements information:
-    # ------------------------------------
-
     ## Get minimum distance between two nodes, elements or distance to the origin
     #  @param id1 first node/element id
     #  @param id2 second node/element id (if 0, distance from @a id1 to the origin is computed)
@@ -2712,6 +2752,7 @@ class Mesh:
     #  @param isElem2 @c True if @a id2 is element id, @c False if it is node id
     #  @return minimum distance value
     #  @sa GetMinDistance()
+    #  @ingroup l1_measurements
     def MinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
         aMeasure = self.GetMinDistance(id1, id2, isElem1, isElem2)
         return aMeasure.value
@@ -2723,6 +2764,7 @@ class Mesh:
     #  @param isElem2 @c True if @a id2 is element id, @c False if it is node id
     #  @return Measure structure
     #  @sa MinDistance()
+    #  @ingroup l1_measurements
     def GetMinDistance(self, id1, id2=0, isElem1=False, isElem2=False):
         if isElem1:
             id1 = self.editor.MakeIDSource([id1], SMESH.FACE)
@@ -2748,6 +2790,7 @@ class Mesh:
     #  @c False specifies that @a objects are nodes
     #  @return tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
     #  @sa GetBoundingBox()
+    #  @ingroup l1_measurements
     def BoundingBox(self, objects=None, isElem=False):
         result = self.GetBoundingBox(objects, isElem)
         if result is None:
@@ -2762,6 +2805,7 @@ class Mesh:
     #  @c False specifies that @a objects are nodes
     #  @return Measure structure
     #  @sa BoundingBox()
+    #  @ingroup l1_measurements
     def GetBoundingBox(self, IDs=None, isElem=False):
         if IDs is None:
             IDs = [self.mesh]
@@ -2796,21 +2840,21 @@ class Mesh:
     # Mesh edition (SMESH_MeshEditor functionality):
     # ---------------------------------------------
 
-    ## Removes the elements from the mesh by ids
+    ## Remove the elements from the mesh by ids
     #  @param IDsOfElements is a list of ids of elements to remove
     #  @return True or False
     #  @ingroup l2_modif_del
     def RemoveElements(self, IDsOfElements):
         return self.editor.RemoveElements(IDsOfElements)
 
-    ## Removes nodes from mesh by ids
+    ## Remove nodes from mesh by ids
     #  @param IDsOfNodes is a list of ids of nodes to remove
     #  @return True or False
     #  @ingroup l2_modif_del
     def RemoveNodes(self, IDsOfNodes):
         return self.editor.RemoveNodes(IDsOfNodes)
 
-    ## Removes all orphan (free) nodes from mesh
+    ## Remove all orphan (free) nodes from mesh
     #  @return number of the removed nodes
     #  @ingroup l2_modif_del
     def RemoveOrphanNodes(self):
@@ -2824,7 +2868,7 @@ class Mesh:
         if hasVars: self.mesh.SetParameters(Parameters)
         return self.editor.AddNode( x, y, z)
 
-    ## Creates a 0D element on a node with given number.
+    ## Create a 0D element on a node with given number.
     #  @param IDOfNode the ID of node for creation of the element.
     #  @param DuplicateElements to add one more 0D element to a node or not
     #  @return the Id of the new 0D element
@@ -2853,7 +2897,7 @@ class Mesh:
             unRegister.set( theObject )
         return self.editor.Create0DElementsOnAllNodes( theObject, theGroupName, DuplicateElements )
 
-    ## Creates a ball element on a node with given ID.
+    ## Create a ball element on a node with given ID.
     #  @param IDOfNode the ID of node for creation of the element.
     #  @param diameter the bal diameter.
     #  @return the Id of the new ball element
@@ -2861,7 +2905,7 @@ class Mesh:
     def AddBall(self, IDOfNode, diameter):
         return self.editor.AddBall( IDOfNode, diameter )
 
-    ## Creates a linear or quadratic edge (this is determined
+    ## Create a linear or quadratic edge (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
     #  The order of nodes in this list should correspond to the description
@@ -2872,7 +2916,7 @@ class Mesh:
     def AddEdge(self, IDsOfNodes):
         return self.editor.AddEdge(IDsOfNodes)
 
-    ## Creates a linear or quadratic face (this is determined
+    ## Create a linear or quadratic face (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
     #  The order of nodes in this list should correspond to the description
@@ -2883,14 +2927,14 @@ class Mesh:
     def AddFace(self, IDsOfNodes):
         return self.editor.AddFace(IDsOfNodes)
 
-    ## Adds a polygonal face to the mesh by the list of node IDs
+    ## Add a polygonal face to the mesh by the list of node IDs
     #  @param IdsOfNodes the list of node IDs for creation of the element.
     #  @return the Id of the new face
     #  @ingroup l2_modif_add
     def AddPolygonalFace(self, IdsOfNodes):
         return self.editor.AddPolygonalFace(IdsOfNodes)
 
-    ## Adds a quadratic polygonal face to the mesh by the list of node IDs
+    ## Add a quadratic polygonal face to the mesh by the list of node IDs
     #  @param IdsOfNodes the list of node IDs for creation of the element;
     #         corner nodes follow first.
     #  @return the Id of the new face
@@ -2898,7 +2942,7 @@ class Mesh:
     def AddQuadPolygonalFace(self, IdsOfNodes):
         return self.editor.AddQuadPolygonalFace(IdsOfNodes)
 
-    ## Creates both simple and quadratic volume (this is determined
+    ## Create both simple and quadratic volume (this is determined
     #  by the number of given nodes).
     #  @param IDsOfNodes the list of node IDs for creation of the element.
     #  The order of nodes in this list should correspond to the description
@@ -2909,7 +2953,7 @@ class Mesh:
     def AddVolume(self, IDsOfNodes):
         return self.editor.AddVolume(IDsOfNodes)
 
-    ## Creates a volume of many faces, giving nodes for each face.
+    ## Create a volume of many faces, giving nodes for each face.
     #  @param IdsOfNodes the list of node IDs for volume creation face by face.
     #  @param Quantities the list of integer values, Quantities[i]
     #         gives the quantity of nodes in face number i.
@@ -2918,7 +2962,7 @@ class Mesh:
     def AddPolyhedralVolume (self, IdsOfNodes, Quantities):
         return self.editor.AddPolyhedralVolume(IdsOfNodes, Quantities)
 
-    ## Creates a volume of many faces, giving the IDs of the existing faces.
+    ## Create a volume of many faces, giving the IDs of the existing faces.
     #  @param IdsOfFaces the list of face IDs for volume creation.
     #
     #  Note:  The created volume will refer only to the nodes
@@ -3014,43 +3058,43 @@ class Mesh:
         return True
 
 
-    ## Moves the node with the given id
+    ## Move the node with the given id
     #  @param NodeID the id of the node
     #  @param x  a new X coordinate
     #  @param y  a new Y coordinate
     #  @param z  a new Z coordinate
     #  @return True if succeed else False
-    #  @ingroup l2_modif_movenode
+    #  @ingroup l2_modif_edit
     def MoveNode(self, NodeID, x, y, z):
         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
         if hasVars: self.mesh.SetParameters(Parameters)
         return self.editor.MoveNode(NodeID, x, y, z)
 
-    ## Finds the node closest to a point and moves it to a point location
+    ## Find the node closest to a point and moves it to a point location
     #  @param x  the X coordinate of a point
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
     #  @param NodeID if specified (>0), the node with this ID is moved,
     #  otherwise, the node closest to point (@a x,@a y,@a z) is moved
     #  @return the ID of a node
-    #  @ingroup l2_modif_throughp
+    #  @ingroup l2_modif_edit
     def MoveClosestNodeToPoint(self, x, y, z, NodeID):
         x,y,z,Parameters,hasVars = ParseParameters(x,y,z)
         if hasVars: self.mesh.SetParameters(Parameters)
         return self.editor.MoveClosestNodeToPoint(x, y, z, NodeID)
 
-    ## Finds the node closest to a point
+    ## Find the node closest to a point
     #  @param x  the X coordinate of a point
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
     #  @return the ID of a node
-    #  @ingroup l2_modif_throughp
+    #  @ingroup l1_meshinfo
     def FindNodeClosestTo(self, x, y, z):
         #preview = self.mesh.GetMeshEditPreviewer()
         #return preview.MoveClosestNodeToPoint(x, y, z, -1)
         return self.editor.FindNodeClosestTo(x, y, z)
 
-    ## Finds the elements where a point lays IN or ON
+    ## Find the elements where a point lays IN or ON
     #  @param x  the X coordinate of a point
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
@@ -3059,7 +3103,7 @@ class Mesh:
     #         means elements of any type excluding nodes, discrete and 0D elements.
     #  @param meshPart a part of mesh (group, sub-mesh) to search within
     #  @return list of IDs of found elements
-    #  @ingroup l2_modif_throughp
+    #  @ingroup l1_meshinfo
     def FindElementsByPoint(self, x, y, z, elementType = SMESH.ALL, meshPart=None):
         if meshPart:
             return self.editor.FindAmongElementsByPoint( meshPart, x, y, z, elementType );
@@ -3069,19 +3113,20 @@ class Mesh:
     ## Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
     #  0-IN, 1-OUT, 2-ON, 3-UNKNOWN
     #  UNKNOWN state means that either mesh is wrong or the analysis fails.
+    #  @ingroup l1_meshinfo
     def GetPointState(self, x, y, z):
         return self.editor.GetPointState(x, y, z)
 
-    ## Finds the node closest to a point and moves it to a point location
+    ## Find the node closest to a point and moves it to a point location
     #  @param x  the X coordinate of a point
     #  @param y  the Y coordinate of a point
     #  @param z  the Z coordinate of a point
     #  @return the ID of a moved node
-    #  @ingroup l2_modif_throughp
+    #  @ingroup l2_modif_edit
     def MeshToPassThroughAPoint(self, x, y, z):
         return self.editor.MoveClosestNodeToPoint(x, y, z, -1)
 
-    ## Replaces two neighbour triangles sharing Node1-Node2 link
+    ## Replace two neighbour triangles sharing Node1-Node2 link
     #  with the triangles built on the same 4 nodes but having other common link.
     #  @param NodeID1  the ID of the first node
     #  @param NodeID2  the ID of the second node
@@ -3090,7 +3135,7 @@ class Mesh:
     def InverseDiag(self, NodeID1, NodeID2):
         return self.editor.InverseDiag(NodeID1, NodeID2)
 
-    ## Replaces two neighbour triangles sharing Node1-Node2 link
+    ## Replace two neighbour triangles sharing Node1-Node2 link
     #  with a quadrangle built on the same 4 nodes.
     #  @param NodeID1  the ID of the first node
     #  @param NodeID2  the ID of the second node
@@ -3099,7 +3144,7 @@ class Mesh:
     def DeleteDiag(self, NodeID1, NodeID2):
         return self.editor.DeleteDiag(NodeID1, NodeID2)
 
-    ## Reorients elements by ids
+    ## Reorient elements by ids
     #  @param IDsOfElements if undefined reorients all mesh elements
     #  @return True if succeed else False
     #  @ingroup l2_modif_changori
@@ -3108,7 +3153,7 @@ class Mesh:
             IDsOfElements = self.GetElementsId()
         return self.editor.Reorient(IDsOfElements)
 
-    ## Reorients all elements of the object
+    ## Reorient all elements of the object
     #  @param theObject mesh, submesh or group
     #  @return True if succeed else False
     #  @ingroup l2_modif_changori
@@ -3185,7 +3230,7 @@ class Mesh:
             unRegister.set( the3DObject )
         return self.editor.Reorient2DBy3D( the2DObject, the3DObject, theOutsideNormal )
 
-    ## Fuses the neighbouring triangles into quadrangles.
+    ## Fuse the neighbouring triangles into quadrangles.
     #  @param IDsOfElements The triangles to be fused.
     #  @param theCriterion  a numerical functor, in terms of enum SMESH.FunctorType, used to
     #          applied to possible quadrangles to choose a neighbour to fuse with.
@@ -3204,7 +3249,7 @@ class Mesh:
         Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.TriToQuad(IDsOfElements, Functor, MaxAngle)
 
-    ## Fuses the neighbouring triangles of the object into quadrangles
+    ## Fuse the neighbouring triangles of the object into quadrangles
     #  @param theObject is mesh, submesh or group
     #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType,
     #          applied to possible quadrangles to choose a neighbour to fuse with.
@@ -3222,7 +3267,7 @@ class Mesh:
         Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.TriToQuadObject(theObject, Functor, MaxAngle)
 
-    ## Splits quadrangles into triangles.
+    ## Split quadrangles into triangles.
     #  @param IDsOfElements the faces to be splitted.
     #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting. If @a theCriterion is None, which is a default
@@ -3239,7 +3284,7 @@ class Mesh:
         Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.QuadToTri(IDsOfElements, Functor)
 
-    ## Splits quadrangles into triangles.
+    ## Split quadrangles into triangles.
     #  @param theObject the object from which the list of elements is taken,
     #         this is mesh, submesh or group
     #  @param theCriterion is a numerical functor, in terms of enum SMESH.FunctorType, used to
@@ -3257,7 +3302,7 @@ class Mesh:
         Functor = self.smeshpyD.GetFunctor(theCriterion)
         return self.editor.QuadToTriObject(theObject, Functor)
 
-    ## Splits each of given quadrangles into 4 triangles. A node is added at the center of
+    ## Split each of given quadrangles into 4 triangles. A node is added at the center of
     #  a quadrangle.
     #  @param theElements the faces to be splitted. This can be either mesh, sub-mesh,
     #         group or a list of face IDs. By default all quadrangles are split
@@ -3273,7 +3318,7 @@ class Mesh:
             unRegister.set( theElements )
         return self.editor.QuadTo4Tri( theElements )
 
-    ## Splits quadrangles into triangles.
+    ## Split quadrangles into triangles.
     #  @param IDsOfElements the faces to be splitted
     #  @param Diag13        is used to choose a diagonal for splitting.
     #  @return TRUE in case of success, FALSE otherwise.
@@ -3283,7 +3328,7 @@ class Mesh:
             IDsOfElements = self.GetElementsId()
         return self.editor.SplitQuad(IDsOfElements, Diag13)
 
-    ## Splits quadrangles into triangles.
+    ## Split quadrangles into triangles.
     #  @param theObject the object from which the list of elements is taken,
     #         this is mesh, submesh or group
     #  @param Diag13    is used to choose a diagonal for splitting.
@@ -3294,7 +3339,7 @@ class Mesh:
             theObject = theObject.GetMesh()
         return self.editor.SplitQuadObject(theObject, Diag13)
 
-    ## Finds a better splitting of the given quadrangle.
+    ## Find a better splitting of the given quadrangle.
     #  @param IDOfQuad   the ID of the quadrangle to be splitted.
     #  @param theCriterion  is a numerical functor, in terms of enum SMESH.FunctorType, used to
     #         choose a diagonal for splitting.
@@ -3306,7 +3351,7 @@ class Mesh:
     def BestSplit (self, IDOfQuad, theCriterion):
         return self.editor.BestSplit(IDOfQuad, self.smeshpyD.GetFunctor(theCriterion))
 
-    ## Splits volumic elements into tetrahedrons
+    ## Split volumic elements into tetrahedrons
     #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
     #  @param method  flags passing splitting method:
     #         smesh.Hex_5Tet, smesh.Hex_6Tet, smesh.Hex_24Tet.
@@ -3344,7 +3389,7 @@ class Mesh:
             elems = [elems]
         self.editor.SplitBiQuadraticIntoLinear( elems )
 
-    ## Splits hexahedra into prisms
+    ## Split hexahedra into prisms
     #  @param elems either a list of elements or a mesh or a group or a submesh or a filter
     #  @param startHexPoint a point used to find a hexahedron for which @a facetNormal
     #         gives a normal vector defining facets to split into triangles.
@@ -3385,9 +3430,9 @@ class Mesh:
 
         self.editor.SplitHexahedraIntoPrisms(elems, startHexPoint, facetNormal, method, allDomains)
 
-    ## Splits quadrangle faces near triangular facets of volumes
+    ## Split quadrangle faces near triangular facets of volumes
     #
-    #  @ingroup l1_auxiliary
+    #  @ingroup l2_modif_cutquadr
     def SplitQuadsNearTriangularFacets(self):
         faces_array = self.GetElementsByType(SMESH.FACE)
         for face_id in faces_array:
@@ -3425,7 +3470,7 @@ class Mesh:
     #         key-point will be mapped into <VAR>theNode001</VAR>-th node of each volume.
     #         The (0,0,0) key-point of the used pattern corresponds to a non-split corner.
     #  @return TRUE in case of success, FALSE otherwise.
-    #  @ingroup l1_auxiliary
+    #  @ingroup l2_modif_cutquadr
     def SplitHexaToTetras (self, theObject, theNode000, theNode001):
         # Pattern:     5.---------.6
         #              /|#*      /|
@@ -3483,7 +3528,7 @@ class Mesh:
     #         will be mapped into the <VAR>theNode001</VAR>-th node of each volume.
     #         Edge (0,0,0)-(0,0,1) of used pattern connects two not split corners.
     #  @return TRUE in case of success, FALSE otherwise.
-    #  @ingroup l1_auxiliary
+    #  @ingroup l2_modif_cutquadr
     def SplitHexaToPrisms (self, theObject, theNode000, theNode001):
         # Pattern:     5.---------.6
         #              /|#       /|
@@ -3522,12 +3567,12 @@ class Mesh:
         isDone = pattern.MakeMesh(self.mesh, False, False)
         if not isDone: print 'Pattern.MakeMesh :', pattern.GetErrorCode()
 
-        # Splits quafrangle faces near triangular facets of volumes
+        # Split quafrangle faces near triangular facets of volumes
         self.SplitQuadsNearTriangularFacets()
 
         return isDone
 
-    ## Smoothes elements
+    ## Smooth elements
     #  @param IDsOfElements the list if ids of elements to smooth
     #  @param IDsOfFixedNodes the list of ids of fixed nodes.
     #  Note that nodes built on edges and boundary nodes are always fixed.
@@ -3546,7 +3591,7 @@ class Mesh:
         return self.editor.Smooth(IDsOfElements, IDsOfFixedNodes,
                                   MaxNbOfIterations, MaxAspectRatio, Method)
 
-    ## Smoothes elements which belong to the given object
+    ## Smooth elements which belong to the given object
     #  @param theObject the object to smooth
     #  @param IDsOfFixedNodes the list of ids of fixed nodes.
     #  Note that nodes built on edges and boundary nodes are always fixed.
@@ -3563,7 +3608,7 @@ class Mesh:
         return self.editor.SmoothObject(theObject, IDsOfFixedNodes,
                                         MaxNbOfIterations, MaxAspectRatio, Method)
 
-    ## Parametrically smoothes the given elements
+    ## Parametrically smooth the given elements
     #  @param IDsOfElements the list if ids of elements to smooth
     #  @param IDsOfFixedNodes the list of ids of fixed nodes.
     #  Note that nodes built on edges and boundary nodes are always fixed.
@@ -3582,7 +3627,7 @@ class Mesh:
         return self.editor.SmoothParametric(IDsOfElements, IDsOfFixedNodes,
                                             MaxNbOfIterations, MaxAspectRatio, Method)
 
-    ## Parametrically smoothes the elements which belong to the given object
+    ## Parametrically smooth the elements which belong to the given object
     #  @param theObject the object to smooth
     #  @param IDsOfFixedNodes the list of ids of fixed nodes.
     #  Note that nodes built on edges and boundary nodes are always fixed.
@@ -3599,13 +3644,14 @@ class Mesh:
         return self.editor.SmoothParametricObject(theObject, IDsOfFixedNodes,
                                                   MaxNbOfIterations, MaxAspectRatio, Method)
 
-    ## Converts the mesh to quadratic or bi-quadratic, deletes old elements, replacing
+    ## Convert the mesh to quadratic or bi-quadratic, deletes old elements, replacing
     #  them with quadratic with the same id.
     #  @param theForce3d new node creation method:
     #         0 - the medium node lies at the geometrical entity from which the mesh element is built
     #         1 - the medium node lies at the middle of the line segments connecting two nodes of a mesh element
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
     #  @param theToBiQuad If True, converts the mesh to bi-quadratic
+    #  @return SMESH.ComputeError which can hold a warning
     #  @ingroup l2_modif_tofromqu
     def ConvertToQuadratic(self, theForce3d=False, theSubMesh=None, theToBiQuad=False):
         if isinstance( theSubMesh, Mesh ):
@@ -3620,8 +3666,9 @@ class Mesh:
         error = self.editor.GetLastError()
         if error and error.comment:
             print error.comment
+        return error
             
-    ## Converts the mesh from quadratic to ordinary,
+    ## Convert the mesh from quadratic to ordinary,
     #  deletes old quadratic elements, \n replacing
     #  them with ordinary mesh elements with the same id.
     #  @param theSubMesh a group or a sub-mesh to convert; WARNING: in this case the mesh can become not conformal
@@ -3632,19 +3679,19 @@ class Mesh:
         else:
             return self.editor.ConvertFromQuadratic()
 
-    ## Creates 2D mesh as skin on boundary faces of a 3D mesh
+    ## Create 2D mesh as skin on boundary faces of a 3D mesh
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_add
     def Make2DMeshFrom3D(self):
         return self.editor.Make2DMeshFrom3D()
 
-    ## Creates missing boundary elements
+    ## Create missing boundary elements
     #  @param elements - elements whose boundary is to be checked:
     #                    mesh, group, sub-mesh or list of elements
     #   if elements is mesh, it must be the mesh whose MakeBoundaryMesh() is called
     #  @param dimension - defines type of boundary elements to create, either of
     #                     { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
-    #    SMESH.BND_1DFROM3D creates mesh edges on all borders of free facets of 3D cells
+    #    SMESH.BND_1DFROM3D create mesh edges on all borders of free facets of 3D cells
     #  @param groupName - a name of group to store created boundary elements in,
     #                     "" means not to create the group
     #  @param meshName - a name of new mesh to store created boundary elements in,
@@ -3654,7 +3701,7 @@ class Mesh:
     #  @param toCopyExistingBondary - if true, not only new but also pre-existing
     #     boundary elements will be copied into the new mesh
     #  @return tuple (mesh, group) where boundary elements were added to
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_add
     def MakeBoundaryMesh(self, elements, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
                          toCopyElements=False, toCopyExistingBondary=False):
         unRegister = genObjUnRegister()
@@ -3671,7 +3718,7 @@ class Mesh:
         return mesh, group
 
     ##
-    # @brief Creates missing boundary elements around either the whole mesh or 
+    # @brief Create missing boundary elements around either the whole mesh or 
     #    groups of elements
     #  @param dimension - defines type of boundary elements to create, either of
     #                     { SMESH.BND_2DFROM3D, SMESH.BND_1DFROM3D, SMESH.BND_1DFROM2D }
@@ -3687,6 +3734,7 @@ class Mesh:
     #                 mesh - the mesh where elements were added to
     #                 group - the group of boundary elements or None
     #
+    #  @ingroup l2_modif_add
     def MakeBoundaryElements(self, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
                              toCopyAll=False, groups=[]):
         nb, mesh, group = self.editor.MakeBoundaryElements(dimension,groupName,meshName,
@@ -3718,7 +3766,7 @@ class Mesh:
             arg = [arg]
         return arg
 
-    ## Generates new elements by rotation of the given elements and nodes around the axis
+    ## Generate new elements by rotation of the given elements and nodes around the axis
     #  @param nodes - nodes to revolve: a list including ids, groups, sub-meshes or a mesh
     #  @param edges - edges to revolve: a list including ids, groups, sub-meshes or a mesh
     #  @param faces - faces to revolve: a list including ids, groups, sub-meshes or a mesh
@@ -3754,7 +3802,7 @@ class Mesh:
                                                  Axis, AngleInRadians,
                                                  NbOfSteps, Tolerance, MakeGroups)
 
-    ## Generates new elements by rotation of the elements around the axis
+    ## Generate new elements by rotation of the elements around the axis
     #  @param IDsOfElements the list of ids of elements to sweep
     #  @param Axis the axis of rotation, AxisStruct or line(geom object)
     #  @param AngleInRadians the angle of Rotation (in radians) or a name of variable which defines angle in degrees
@@ -3771,7 +3819,7 @@ class Mesh:
                                          AngleInRadians, NbOfSteps, Tolerance,
                                          MakeGroups, TotalAngle)
 
-    ## Generates new elements by rotation of the elements of object around the axis
+    ## Generate new elements by rotation of the elements of object around the axis
     #  @param theObject object which elements should be sweeped.
     #                   It can be a mesh, a sub mesh or a group.
     #  @param Axis the axis of rotation, AxisStruct or line(geom object)
@@ -3789,7 +3837,7 @@ class Mesh:
                                           AngleInRadians, NbOfSteps, Tolerance,
                                           MakeGroups, TotalAngle )
 
-    ## Generates new elements by rotation of the elements of object around the axis
+    ## Generate new elements by rotation of the elements of object around the axis
     #  @param theObject object which elements should be sweeped.
     #                   It can be a mesh, a sub mesh or a group.
     #  @param Axis the axis of rotation, AxisStruct or line(geom object)
@@ -3807,7 +3855,7 @@ class Mesh:
                                          AngleInRadians, NbOfSteps, Tolerance,
                                          MakeGroups, TotalAngle)
 
-    ## Generates new elements by rotation of the elements of object around the axis
+    ## Generate new elements by rotation of the elements of object around the axis
     #  @param theObject object which elements should be sweeped.
     #                   It can be a mesh, a sub mesh or a group.
     #  @param Axis the axis of rotation, AxisStruct or line(geom object)
@@ -3824,7 +3872,7 @@ class Mesh:
         return self.RotationSweepObjects([],[],theObject, Axis, AngleInRadians,
                                          NbOfSteps, Tolerance, MakeGroups, TotalAngle)
 
-    ## Generates new elements by extrusion of the given elements and nodes
+    ## Generate new elements by extrusion of the given elements and nodes
     #  @param nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh
     #  @param edges edges to extrude: a list including ids, groups, sub-meshes or a mesh
     #  @param faces faces to extrude: a list including ids, groups, sub-meshes or a mesh
@@ -3844,6 +3892,7 @@ class Mesh:
     #         - a GEOM point
     #  @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
                               scaleFactors=[], linearVariation=False, basePoint=[] ):
         unRegister = genObjUnRegister()
@@ -3874,7 +3923,7 @@ class Mesh:
                                                   MakeGroups)
 
 
-    ## Generates new elements by extrusion of the elements with given ids
+    ## Generate new elements by extrusion of the elements with given ids
     #  @param IDsOfElements the list of ids of elements or nodes for extrusion
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
@@ -3884,13 +3933,14 @@ class Mesh:
     #  @param IsNodes is True if elements with given ids are nodes
     #  @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweep(self, IDsOfElements, StepVector, NbOfSteps, MakeGroups=False, IsNodes = False):
         n,e,f = [],[],[]
         if IsNodes: n = IDsOfElements
         else      : e,f, = IDsOfElements,IDsOfElements
         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion along the normal to a discretized surface or wire
+    ## Generate new elements by extrusion along the normal to a discretized surface or wire
     #  @param Elements elements to extrude - a list including ids, groups, sub-meshes or a mesh.
     #         Only faces can be extruded so far. A sub-mesh should be a sub-mesh on geom faces.
     #  @param StepSize length of one extrusion step (the total extrusion
@@ -3910,6 +3960,7 @@ class Mesh:
     #  @return the list of created groups (SMESH_GroupBase) if \a MakeGroups=True,
     #          empty list otherwise.
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionByNormal(self, Elements, StepSize, NbOfSteps,
                           ByAverageNormal=False, UseInputElemsOnly=True, MakeGroups=False, Dim = 2):
         unRegister = genObjUnRegister()
@@ -3928,7 +3979,7 @@ class Mesh:
         return self.editor.ExtrusionByNormal(Elements, StepSize, NbOfSteps,
                                              ByAverageNormal, UseInputElemsOnly, MakeGroups, Dim)
 
-    ## Generates new elements by extrusion of the elements or nodes which belong to the object
+    ## Generate new elements by extrusion of the elements or nodes which belong to the object
     #  @param theObject the object whose elements or nodes should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
@@ -3939,13 +3990,14 @@ class Mesh:
     #  @param IsNodes is True if elements to extrude are nodes
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject(self, theObject, StepVector, NbOfSteps, MakeGroups=False, IsNodes=False):
         n,e,f = [],[],[]
         if IsNodes: n    = theObject
         else      : e,f, = theObject,theObject
         return self.ExtrusionSweepObjects(n,e,f, StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion of edges which belong to the object
+    ## Generate new elements by extrusion of edges which belong to the object
     #  @param theObject object whose 1D elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
@@ -3955,10 +4007,11 @@ class Mesh:
     #  @param MakeGroups to generate new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject1D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
         return self.ExtrusionSweepObjects([],theObject,[], StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion of faces which belong to the object
+    ## Generate new elements by extrusion of faces which belong to the object
     #  @param theObject object whose 2D elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
     #  @param StepVector vector or DirStruct or 3 vector components, defining
@@ -3968,10 +4021,11 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion example
     def ExtrusionSweepObject2D(self, theObject, StepVector, NbOfSteps, MakeGroups=False):
         return self.ExtrusionSweepObjects([],[],theObject, StepVector, NbOfSteps, MakeGroups)
 
-    ## Generates new elements by extrusion of the elements with given ids
+    ## Generate new elements by extrusion of the elements with given ids
     #  @param IDsOfElements is ids of elements
     #  @param StepVector vector or DirStruct or 3 vector components, defining
     #         the direction and value of extrusion for one step (the total extrusion
@@ -3992,7 +4046,7 @@ class Mesh:
         return self.editor.AdvancedExtrusion(IDsOfElements, StepVector, NbOfSteps,
                                              ExtrFlags, SewTolerance, MakeGroups)
 
-    ## Generates new elements by extrusion of the given elements and nodes along the path.
+    ## Generate new elements by extrusion of the given elements and nodes along the path.
     #  The path of extrusion must be a meshed edge.
     #  @param Nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh
     #  @param Edges edges to extrude: a list including ids, groups, sub-meshes or a mesh
@@ -4012,6 +4066,7 @@ class Mesh:
     #  @param MakeGroups forces the generation of new groups from existing ones
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObjects(self, Nodes, Edges, Faces, PathMesh, PathShape=None,
                                   NodeStart=1, HasAngles=False, Angles=[], LinearVariation=False,
                                   HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False):
@@ -4035,7 +4090,7 @@ class Mesh:
                                                      HasAngles, Angles, LinearVariation,
                                                      HasRefPoint, RefPoint, MakeGroups)
 
-    ## Generates new elements by extrusion of the given elements
+    ## Generate new elements by extrusion of the given elements
     #  The path of extrusion must be a meshed edge.
     #  @param Base mesh or group, or sub-mesh, or list of ids of elements for extrusion
     #  @param Path - 1D mesh or 1D sub-mesh, along which proceeds the extrusion
@@ -4055,6 +4110,7 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathX(self, Base, Path, NodeStart,
                             HasAngles=False, Angles=[], LinearVariation=False,
                             HasRefPoint=False, RefPoint=[0,0,0], MakeGroups=False,
@@ -4069,7 +4125,7 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of the given elements
+    ## Generate new elements by extrusion of the given elements
     #  The path of extrusion must be a meshed edge.
     #  @param IDsOfElements ids of elements
     #  @param PathMesh mesh containing a 1D sub-mesh on the edge, along which proceeds the extrusion
@@ -4087,6 +4143,7 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPath(self, IDsOfElements, PathMesh, PathShape, NodeStart,
                            HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                            MakeGroups=False, LinearVariation=False):
@@ -4098,7 +4155,7 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of the elements which belong to the object
+    ## Generate new elements by extrusion of the elements which belong to the object
     #  The path of extrusion must be a meshed edge.
     #  @param theObject the object whose elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
@@ -4117,6 +4174,7 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject(self, theObject, PathMesh, PathShape, NodeStart,
                                  HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                  MakeGroups=False, LinearVariation=False):
@@ -4127,7 +4185,7 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of mesh segments which belong to the object
+    ## Generate new elements by extrusion of mesh segments which belong to the object
     #  The path of extrusion must be a meshed edge.
     #  @param theObject the object whose 1D elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
@@ -4146,6 +4204,7 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject1D(self, theObject, PathMesh, PathShape, NodeStart,
                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
@@ -4156,7 +4215,7 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Generates new elements by extrusion of faces which belong to the object
+    ## Generate new elements by extrusion of faces which belong to the object
     #  The path of extrusion must be a meshed edge.
     #  @param theObject the object whose 2D elements should be processed.
     #                   It can be a mesh, a sub-mesh or a group.
@@ -4175,6 +4234,7 @@ class Mesh:
     #  @return list of created groups (SMESH_GroupBase) and SMESH::Extrusion_Error if MakeGroups=True,
     #          only SMESH::Extrusion_Error otherwise
     #  @ingroup l2_modif_extrurev
+    #  @ref tui_extrusion_along_path example
     def ExtrusionAlongPathObject2D(self, theObject, PathMesh, PathShape, NodeStart,
                                    HasAngles=False, Angles=[], HasRefPoint=False, RefPoint=[],
                                    MakeGroups=False, LinearVariation=False):
@@ -4185,7 +4245,7 @@ class Mesh:
         if MakeGroups: return gr,er
         return er
 
-    ## Creates a symmetrical copy of mesh elements
+    ## Create a symmetrical copy of mesh elements
     #  @param IDsOfElements list of elements ids
     #  @param Mirror is AxisStruct or geom object(point, line, plane)
     #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
@@ -4207,7 +4267,7 @@ class Mesh:
         self.editor.Mirror(IDsOfElements, Mirror, theMirrorType, Copy)
         return []
 
-    ## Creates a new mesh by a symmetrical copy of mesh elements
+    ## Create a new mesh by a symmetrical copy of mesh elements
     #  @param IDsOfElements the list of elements ids
     #  @param Mirror is AxisStruct or geom object (point, line, plane)
     #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
@@ -4228,7 +4288,7 @@ class Mesh:
                                           MakeGroups, NewMeshName)
         return Mesh(self.smeshpyD,self.geompyD,mesh)
 
-    ## Creates a symmetrical copy of the object
+    ## Create a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
     #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
@@ -4250,7 +4310,7 @@ class Mesh:
         self.editor.MirrorObject(theObject, Mirror, theMirrorType, Copy)
         return []
 
-    ## Creates a new mesh by a symmetrical copy of the object
+    ## Create a new mesh by a symmetrical copy of the object
     #  @param theObject mesh, submesh or group
     #  @param Mirror AxisStruct or geom object (point, line, plane)
     #  @param theMirrorType smeshBuilder.POINT, smeshBuilder.AXIS or smeshBuilder.PLANE
@@ -4271,7 +4331,7 @@ class Mesh:
                                                 MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD,self.geompyD,mesh )
 
-    ## Translates the elements
+    ## Translate the elements
     #  @param IDsOfElements list of elements ids
     #  @param Vector the direction of translation (DirStruct or vector or 3 vector components)
     #  @param Copy allows copying the translated elements
@@ -4291,7 +4351,7 @@ class Mesh:
         self.editor.Translate(IDsOfElements, Vector, Copy)
         return []
 
-    ## Creates a new mesh of translated elements
+    ## Create a new mesh of translated elements
     #  @param IDsOfElements list of elements ids
     #  @param Vector the direction of translation (DirStruct or vector or 3 vector components)
     #  @param MakeGroups forces the generation of new groups from existing ones
@@ -4309,7 +4369,7 @@ class Mesh:
         mesh = self.editor.TranslateMakeMesh(IDsOfElements, Vector, MakeGroups, NewMeshName)
         return Mesh ( self.smeshpyD, self.geompyD, mesh )
 
-    ## Translates the object
+    ## Translate the object
     #  @param theObject the object to translate (mesh, submesh, or group)
     #  @param Vector direction of translation (DirStruct or geom vector or 3 vector components)
     #  @param Copy allows copying the translated elements
@@ -4329,7 +4389,7 @@ class Mesh:
         self.editor.TranslateObject(theObject, Vector, Copy)
         return []
 
-    ## Creates a new mesh from the translated object
+    ## Create a new mesh from the translated object
     #  @param theObject the object to translate (mesh, submesh, or group)
     #  @param Vector the direction of translation (DirStruct or geom vector or 3 vector components)
     #  @param MakeGroups forces the generation of new groups from existing ones
@@ -4349,7 +4409,7 @@ class Mesh:
 
 
 
-    ## Scales the object
+    ## Scale the object
     #  @param theObject - the object to translate (mesh, submesh, or group)
     #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
@@ -4379,7 +4439,7 @@ class Mesh:
         self.editor.Scale(theObject, thePoint, theScaleFact, Copy)
         return []
 
-    ## Creates a new mesh from the translated object
+    ## Create a new mesh from the translated object
     #  @param theObject - the object to translate (mesh, submesh, or group)
     #  @param thePoint - base point for scale (SMESH.PointStruct or list of 3 coordinates)
     #  @param theScaleFact - list of 1-3 scale factors for axises
@@ -4407,7 +4467,7 @@ class Mesh:
 
 
 
-    ## Rotates the elements
+    ## Rotate the elements
     #  @param IDsOfElements list of elements ids
     #  @param Axis the axis of rotation (AxisStruct or geom line)
     #  @param AngleInRadians the angle of rotation (in radians) or a name of variable which defines angle in degrees
@@ -4428,7 +4488,7 @@ class Mesh:
         self.editor.Rotate(IDsOfElements, Axis, AngleInRadians, Copy)
         return []
 
-    ## Creates a new mesh of rotated elements
+    ## Create a new mesh of rotated elements
     #  @param IDsOfElements list of element ids
     #  @param Axis the axis of rotation (AxisStruct or geom line)
     #  @param AngleInRadians the angle of rotation (in radians) or a name of variable which defines angle in degrees
@@ -4448,7 +4508,7 @@ class Mesh:
                                           MakeGroups, NewMeshName)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
 
-    ## Rotates the object
+    ## Rotate the object
     #  @param theObject the object to rotate( mesh, submesh, or group)
     #  @param Axis the axis of rotation (AxisStruct or geom line)
     #  @param AngleInRadians the angle of rotation (in radians) or a name of variable which defines angle in degrees
@@ -4469,7 +4529,7 @@ class Mesh:
         self.editor.RotateObject(theObject, Axis, AngleInRadians, Copy)
         return []
 
-    ## Creates a new mesh from the rotated object
+    ## Create a new mesh from the rotated object
     #  @param theObject the object to rotate (mesh, submesh, or group)
     #  @param Axis the axis of rotation (AxisStruct or geom line)
     #  @param AngleInRadians the angle of rotation (in radians)  or a name of variable which defines angle in degrees
@@ -4489,7 +4549,7 @@ class Mesh:
         self.mesh.SetParameters(Parameters)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
 
-    ## Finds groups of adjacent nodes within Tolerance.
+    ## Find groups of adjacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
     #  @param SeparateCornerAndMediumNodes if @c True, in quadratic mesh puts
     #         corner and medium nodes in separate groups thus preventing
@@ -4499,7 +4559,7 @@ class Mesh:
     def FindCoincidentNodes (self, Tolerance, SeparateCornerAndMediumNodes=False):
         return self.editor.FindCoincidentNodes( Tolerance, SeparateCornerAndMediumNodes )
 
-    ## Finds groups of ajacent nodes within Tolerance.
+    ## Find groups of ajacent nodes within Tolerance.
     #  @param Tolerance the value of tolerance
     #  @param SubMeshOrGroup SubMesh, Group or Filter
     #  @param exceptNodes list of either SubMeshes, Groups or node IDs to exclude from search
@@ -4521,19 +4581,21 @@ class Mesh:
         return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,
                                                         exceptNodes, SeparateCornerAndMediumNodes)
 
-    ## Merges nodes
+    ## Merge nodes
     #  @param GroupsOfNodes a list of groups of nodes IDs for merging
     #         (e.g. [[1,12,13],[25,4]], then nodes 12, 13 and 4 will be removed and replaced
     #         by nodes 1 and 25 correspondingly in all elements and groups
     #  @param NodesToKeep nodes to keep in the mesh: a list of groups, sub-meshes or node IDs.
     #         If @a NodesToKeep does not include a node to keep for some group to merge,
     #         then the first node in the group is kept.
+    #  @param AvoidMakingHoles prevent merging nodes which cause removal of elements becoming
+    #         invalid
     #  @ingroup l2_modif_trsf
-    def MergeNodes (self, GroupsOfNodes, NodesToKeep=[]):
+    def MergeNodes (self, GroupsOfNodes, NodesToKeep=[], AvoidMakingHoles=False):
         # NodesToKeep are converted to SMESH_IDSource in meshEditor.MergeNodes()
-        self.editor.MergeNodes(GroupsOfNodes,NodesToKeep)
+        self.editor.MergeNodes( GroupsOfNodes, NodesToKeep, AvoidMakingHoles )
 
-    ## Finds the elements built on the same nodes.
+    ## Find the elements built on the same nodes.
     #  @param MeshOrSubMeshOrGroup Mesh or SubMesh, or Group of elements for searching
     #  @return the list of groups of equal elements IDs (e.g. [[1,12,13],[4,25]])
     #  @ingroup l2_modif_trsf
@@ -4544,7 +4606,7 @@ class Mesh:
             MeshOrSubMeshOrGroup = MeshOrSubMeshOrGroup.GetMesh()
         return self.editor.FindEqualElements( MeshOrSubMeshOrGroup )
 
-    ## Merges elements in each given group.
+    ## Merge elements in each given group.
     #  @param GroupsOfElementsID a list of groups of elements IDs for merging
     #        (e.g. [[1,12,13],[25,4]], then elements 12, 13 and 4 will be removed and
     #        replaced by elements 1 and 25 in all groups)
@@ -4552,12 +4614,12 @@ class Mesh:
     def MergeElements(self, GroupsOfElementsID):
         self.editor.MergeElements(GroupsOfElementsID)
 
-    ## Leaves one element and removes all other elements built on the same nodes.
+    ## Leave one element and remove all other elements built on the same nodes.
     #  @ingroup l2_modif_trsf
     def MergeEqualElements(self):
         self.editor.MergeEqualElements()
 
-    ## Returns groups of FreeBorder's coincident within the given tolerance.
+    ## Return groups of FreeBorder's coincident within the given tolerance.
     #  @param tolerance the tolerance. If the tolerance <= 0.0 then one tenth of an average
     #         size of elements adjacent to free borders being compared is used.
     #  @return SMESH.CoincidentFreeBorders structure
@@ -4603,7 +4665,7 @@ class Mesh:
 
         return self.editor.SewCoincidentFreeBorders( freeBorders, createPolygons, createPolyhedra )
 
-    ## Sews free borders
+    ## Sew free borders
     #  @return SMESH::Sew_Error
     #  @ingroup l2_modif_trsf
     def SewFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
@@ -4613,7 +4675,7 @@ class Mesh:
                                           FirstNodeID2, SecondNodeID2, LastNodeID2,
                                           CreatePolygons, CreatePolyedrs)
 
-    ## Sews conform free borders
+    ## Sew conform free borders
     #  @return SMESH::Sew_Error
     #  @ingroup l2_modif_trsf
     def SewConformFreeBorders (self, FirstNodeID1, SecondNodeID1, LastNodeID1,
@@ -4621,7 +4683,7 @@ class Mesh:
         return self.editor.SewConformFreeBorders(FirstNodeID1, SecondNodeID1, LastNodeID1,
                                                  FirstNodeID2, SecondNodeID2)
 
-    ## Sews border to side
+    ## Sew border to side
     #  @return SMESH::Sew_Error
     #  @ingroup l2_modif_trsf
     def SewBorderToSide (self, FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
@@ -4629,7 +4691,7 @@ class Mesh:
         return self.editor.SewBorderToSide(FirstNodeIDOnFreeBorder, SecondNodeIDOnFreeBorder, LastNodeIDOnFreeBorder,
                                            FirstNodeIDOnSide, LastNodeIDOnSide, CreatePolygons, CreatePolyedrs)
 
-    ## Sews two sides of a mesh. The nodes belonging to Side1 are
+    ## Sew two sides of a mesh. The nodes belonging to Side1 are
     #  merged with the nodes of elements of Side2.
     #  The number of elements in theSide1 and in theSide2 must be
     #  equal and they should have similar nodal connectivity.
@@ -4644,36 +4706,36 @@ class Mesh:
                                            NodeID1OfSide1ToMerge, NodeID1OfSide2ToMerge,
                                            NodeID2OfSide1ToMerge, NodeID2OfSide2ToMerge)
 
-    ## Sets new nodes for the given element.
+    ## Set new nodes for the given element.
     #  @param ide the element id
     #  @param newIDs nodes ids
-    #  @return If the number of nodes does not correspond to the type of element - returns false
+    #  @return If the number of nodes does not correspond to the type of element - return false
     #  @ingroup l2_modif_edit
     def ChangeElemNodes(self, ide, newIDs):
         return self.editor.ChangeElemNodes(ide, newIDs)
 
     ## If during the last operation of MeshEditor some nodes were
-    #  created, this method returns the list of their IDs, \n
-    #  if new nodes were not created - returns empty list
+    #  created, this method return the list of their IDs, \n
+    #  if new nodes were not created - return empty list
     #  @return the list of integer values (can be empty)
-    #  @ingroup l1_auxiliary
+    #  @ingroup l2_modif_add
     def GetLastCreatedNodes(self):
         return self.editor.GetLastCreatedNodes()
 
     ## If during the last operation of MeshEditor some elements were
-    #  created this method returns the list of their IDs, \n
-    #  if new elements were not created - returns empty list
+    #  created this method return the list of their IDs, \n
+    #  if new elements were not created - return empty list
     #  @return the list of integer values (can be empty)
-    #  @ingroup l1_auxiliary
+    #  @ingroup l2_modif_add
     def GetLastCreatedElems(self):
         return self.editor.GetLastCreatedElems()
 
-    ## Clears sequences of nodes and elements created by mesh edition oparations
-    #  @ingroup l1_auxiliary
+    ## Forget what nodes and elements were created by the last mesh edition operation
+    #  @ingroup l2_modif_add
     def ClearLastCreated(self):
         self.editor.ClearLastCreated()
 
-    ## Creates duplicates of given elements, i.e. creates new elements based on the 
+    ## Create duplicates of given elements, i.e. create 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
@@ -4684,7 +4746,7 @@ class Mesh:
     #                    If \a theGroupName is empty, new elements are not added 
     #                    in any group.
     # @return a group where the new elements are added. None if theGroupName == "".
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleElements(self, theElements, theGroupName=""):
         unRegister = genObjUnRegister()
         if isinstance( theElements, Mesh ):
@@ -4694,62 +4756,62 @@ class Mesh:
             unRegister.set( theElements )
         return self.editor.DoubleElements(theElements, theGroupName)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  @param theNodes identifiers of nodes to be doubled
     #  @param theModifiedElems identifiers of elements to be updated by the new (doubled)
     #         nodes. If list of element identifiers is empty then nodes are doubled but
     #         they not assigned to elements
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodes(self, theNodes, theModifiedElems):
         return self.editor.DoubleNodes(theNodes, theModifiedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theNodeId identifiers of node to be doubled
     #  @param theModifiedElems identifiers of elements to be updated
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNode(self, theNodeId, theModifiedElems):
         return self.editor.DoubleNode(theNodeId, theModifiedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theNodes group of nodes to be doubled
     #  @param theModifiedElems group of elements to be updated.
     #  @param theMakeGroup forces the generation of a group containing new nodes.
     #  @return TRUE or a created group if operation has been completed successfully,
     #          FALSE or None otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeGroup(self, theNodes, theModifiedElems, theMakeGroup=False):
         if theMakeGroup:
             return self.editor.DoubleNodeGroupNew(theNodes, theModifiedElems)
         return self.editor.DoubleNodeGroup(theNodes, theModifiedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theNodes list of groups of nodes to be doubled
     #  @param theModifiedElems list of groups of elements to be updated.
     #  @param theMakeGroup forces the generation of a group containing new nodes.
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeGroups(self, theNodes, theModifiedElems, theMakeGroup=False):
         if theMakeGroup:
             return self.editor.DoubleNodeGroupsNew(theNodes, theModifiedElems)
         return self.editor.DoubleNodeGroups(theNodes, theModifiedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  @param theElems - the list of elements (edges or faces) to be replicated
     #         The nodes for duplication could be found from these elements
     #  @param theNodesNot - list of nodes to NOT replicate
     #  @param theAffectedElems - the list of elements (cells and edges) to which the
     #         replicated nodes should be associated to.
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElem(self, theElems, theNodesNot, theAffectedElems):
         return self.editor.DoubleNodeElem(theElems, theNodesNot, theAffectedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  @param theElems - the list of elements (edges or faces) to be replicated
     #         The nodes for duplication could be found from these elements
     #  @param theNodesNot - list of nodes to NOT replicate
@@ -4757,11 +4819,11 @@ class Mesh:
     #         located on or inside shape).
     #         The replicated nodes should be associated to affected elements.
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElemInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.DoubleNodeElemInRegion(theElems, theNodesNot, theShape)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theElems - group of of elements (edges or faces) to be replicated
     #  @param theNodesNot - group of nodes not to replicated
@@ -4771,7 +4833,7 @@ class Mesh:
     #  @param theMakeNodeGroup forces the generation of a group containing new nodes.
     #  @return TRUE or created groups (one or two) if operation has been completed successfully,
     #          FALSE or None otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElemGroup(self, theElems, theNodesNot, theAffectedElems,
                              theMakeGroup=False, theMakeNodeGroup=False):
         if theMakeGroup or theMakeNodeGroup:
@@ -4784,18 +4846,18 @@ class Mesh:
                 return twoGroups[ int(theMakeNodeGroup) ]
         return self.editor.DoubleNodeElemGroup(theElems, theNodesNot, theAffectedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theElems - group of of elements (edges or faces) to be replicated
     #  @param theNodesNot - group of nodes not to replicated
     #  @param theShape - shape to detect affected elements (element which geometric center
     #         located on or inside shape).
     #         The replicated nodes should be associated to affected elements.
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElemGroupInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.DoubleNodeElemGroupInRegion(theElems, theNodesNot, theShape)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theElems - list of groups of elements (edges or faces) to be replicated
     #  @param theNodesNot - list of groups of nodes not to replicated
@@ -4805,7 +4867,7 @@ class Mesh:
     #  @param theMakeNodeGroup forces the generation of a group containing new nodes.
     #  @return TRUE or created groups (one or two) if operation has been completed successfully,
     #          FALSE or None otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElemGroups(self, theElems, theNodesNot, theAffectedElems,
                              theMakeGroup=False, theMakeNodeGroup=False):
         if theMakeGroup or theMakeNodeGroup:
@@ -4818,7 +4880,7 @@ class Mesh:
                 return twoGroups[ int(theMakeNodeGroup) ]
         return self.editor.DoubleNodeElemGroups(theElems, theNodesNot, theAffectedElems)
 
-    ## Creates a hole in a mesh by doubling the nodes of some particular elements
+    ## Create a hole in a mesh by doubling the nodes of some particular elements
     #  This method provided for convenience works as DoubleNodes() described above.
     #  @param theElems - list of groups of elements (edges or faces) to be replicated
     #  @param theNodesNot - list of groups of nodes not to replicated
@@ -4826,7 +4888,7 @@ class Mesh:
     #         located on or inside shape).
     #         The replicated nodes should be associated to affected elements.
     #  @return TRUE if operation has been completed successfully, FALSE otherwise
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def DoubleNodeElemGroupsInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.DoubleNodeElemGroupsInRegion(theElems, theNodesNot, theShape)
 
@@ -4838,30 +4900,32 @@ class Mesh:
     #         located on or inside shape).
     #         The replicated nodes should be associated to affected elements.
     #  @return groups of affected elements
-    #  @ingroup l2_modif_edit
+    #  @ingroup l2_modif_duplicat
     def AffectedElemGroupsInRegion(self, theElems, theNodesNot, theShape):
         return self.editor.AffectedElemGroupsInRegion(theElems, theNodesNot, theShape)
 
     ## Double nodes on shared faces between groups of volumes and create flat elements on demand.
-    # The list of groups must describe a partition of the mesh volumes.
-    # The nodes of the internal faces at the boundaries of the groups are doubled.
-    # In option, the internal faces are replaced by flat elements.
-    # Triangles are transformed in prisms, and quadrangles in hexahedrons.
-    # @param theDomains - list of groups of volumes
-    # @param createJointElems - if TRUE, create the elements
-    # @param onAllBoundaries - if TRUE, the nodes and elements are also created on
-    #        the boundary between \a theDomains and the rest mesh
-    # @return TRUE if operation has been completed successfully, FALSE otherwise
+    #  The list of groups must describe a partition of the mesh volumes.
+    #  The nodes of the internal faces at the boundaries of the groups are doubled.
+    #  In option, the internal faces are replaced by flat elements.
+    #  Triangles are transformed in prisms, and quadrangles in hexahedrons.
+    #  @param theDomains - list of groups of volumes
+    #  @param createJointElems - if TRUE, create the elements
+    #  @param onAllBoundaries - if TRUE, the nodes and elements are also created on
+    #         the boundary between \a theDomains and the rest mesh
+    #  @return TRUE if operation has been completed successfully, FALSE otherwise
+    #  @ingroup l2_modif_duplicat
     def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems, onAllBoundaries=False ):
        return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems, onAllBoundaries )
 
     ## Double nodes on some external faces and create flat elements.
-    # Flat elements are mainly used by some types of mechanic calculations.
-    #
-    # Each group of the list must be constituted of faces.
-    # Triangles are transformed in prisms, and quadrangles in hexahedrons.
-    # @param theGroupsOfFaces - list of groups of faces
-    # @return TRUE if operation has been completed successfully, FALSE otherwise
+    #  Flat elements are mainly used by some types of mechanic calculations.
+    #  
+    #  Each group of the list must be constituted of faces.
+    #  Triangles are transformed in prisms, and quadrangles in hexahedrons.
+    #  @param theGroupsOfFaces - list of groups of faces
+    #  @return TRUE if operation has been completed successfully, FALSE otherwise
+    #  @ingroup l2_modif_duplicat
     def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
         return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
     
@@ -4870,6 +4934,32 @@ class Mesh:
     def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
 
+    ## Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+    #  the initial mesh. Positions of new nodes are found by cutting the mesh by the
+    #  plane passing through pairs of points specified by each PolySegment structure.
+    #  If there are several paths connecting a pair of points, the shortest path is
+    #  selected by the module. Position of the cutting plane is defined by the two
+    #  points and an optional vector lying on the plane specified by a PolySegment.
+    #  By default the vector is defined by Mesh module as following. A middle point
+    #  of the two given points is computed. The middle point is projected to the mesh.
+    #  The vector goes from the middle point to the projection point. In case of planar
+    #  mesh, the vector is normal to the mesh.
+    #  @param segments - PolySegment's defining positions of cutting planes.
+    #         Return the used vector which goes from the middle point to its projection.
+    #  @param groupName - optional name of a group where created mesh segments will
+    #         be added.
+    #  @ingroup l2_modif_duplicat
+    def MakePolyLine(self, segments, groupName='', isPreview=False ):
+        editor = self.editor
+        if isPreview:
+            editor = self.mesh.GetMeshEditPreviewer()
+        segmentsRes = editor.MakePolyLine( segments, groupName )
+        for i, seg in enumerate( segmentsRes ):
+            segments[i].vector = seg.vector
+        if isPreview:
+            return editor.GetPreviewData()
+        return None
+
     def _getFunctor(self, funcType ):
         fn = self.functors[ funcType._v ]
         if not fn:
@@ -4878,12 +4968,13 @@ class Mesh:
             self.functors[ funcType._v ] = fn
         return fn
 
-    ## Returns value of a functor for a given element
+    ## Return value of a functor for a given element
     #  @param funcType an item of SMESH.FunctorType enum
     #         Type "SMESH.FunctorType._items" in the Python Console to see all items.
     #  @param elemId element or node ID
     #  @param isElem @a elemId is ID of element or node
     #  @return the functor value or zero in case of invalid arguments
+    #  @ingroup l1_measurements
     def FunctorValue(self, funcType, elemId, isElem=True):
         fn = self._getFunctor( funcType )
         if fn.GetElementType() == self.GetElementType(elemId, isElem):
@@ -5006,7 +5097,7 @@ class Mesh:
     pass # end of Mesh class
 
 
-## Class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
+## Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
 #  with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
 #
 class meshProxy(SMESH._objref_SMESH_Mesh):
@@ -5023,7 +5114,7 @@ class meshProxy(SMESH._objref_SMESH_Mesh):
 omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
 
 
-## Class wrapping SMESH_SubMesh in order to add Compute()
+## Private class wrapping SMESH.SMESH_SubMesh in order to add Compute()
 #
 class submeshProxy(SMESH._objref_SMESH_subMesh):
     def __init__(self):
@@ -5033,10 +5124,13 @@ class submeshProxy(SMESH._objref_SMESH_subMesh):
         new = self.__class__()
         return new
 
-    ## Computes the sub-mesh and returns the status of the computation
+    ## Compute the sub-mesh and return the status of the computation
     #  @param refresh if @c True, Object browser is automatically updated (when running in GUI)
     #  @return True or False
-    #  @ingroup l2_construct
+    #
+    #  This is a method of SMESH.SMESH_submesh that can be obtained via Mesh.GetSubMesh() or
+    #  @ref smesh_algorithm.Mesh_Algorithm.GetSubMesh() "Mesh_Algorithm.GetSubMesh()".
+    #  @ingroup l2_submeshes
     def Compute(self,refresh=False):
         if not self.mesh:
             self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
@@ -5055,8 +5149,9 @@ class submeshProxy(SMESH._objref_SMESH_subMesh):
 omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
 
 
-## Class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
-#  with old dump scripts which call SMESH_MeshEditor directly and not via smeshBuilder.Mesh
+## Private class used to compensate change of CORBA API of SMESH_MeshEditor for backward
+#  compatibility with old dump scripts which call SMESH_MeshEditor directly and not via
+#  smeshBuilder.Mesh
 #
 class meshEditor(SMESH._objref_SMESH_MeshEditor):
     def __init__(self):
@@ -5080,21 +5175,23 @@ class meshEditor(SMESH._objref_SMESH_MeshEditor):
     def FindCoincidentNodesOnPart(self,*args): # a 3d arg added (SeparateCornerAndMediumNodes)
         if len( args ) == 2: args += False,
         return SMESH._objref_SMESH_MeshEditor.FindCoincidentNodesOnPart( self, *args )
-    def MergeNodes(self,*args): # a 2nd arg added (NodesToKeep)
+    def MergeNodes(self,*args): # 2 args added (NodesToKeep,AvoidMakingHoles)
         if len( args ) == 1:
-            return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [] )
+            return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], [], False )
         NodesToKeep = args[1]
+        AvoidMakingHoles = args[2] if len( args ) == 3 else False
         unRegister  = genObjUnRegister()
         if NodesToKeep:
             if isinstance( NodesToKeep, list ) and isinstance( NodesToKeep[0], int ):
                 NodesToKeep = self.MakeIDSource( NodesToKeep, SMESH.NODE )
             if not isinstance( NodesToKeep, list ):
                 NodesToKeep = [ NodesToKeep ]
-        return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep )
+        return SMESH._objref_SMESH_MeshEditor.MergeNodes( self, args[0], NodesToKeep, AvoidMakingHoles )
     pass
 omniORB.registerObjref(SMESH._objref_SMESH_MeshEditor._NP_RepositoryId, meshEditor)
 
-## Helper class for wrapping of SMESH.SMESH_Pattern CORBA class
+## Private class wrapping SMESH.SMESH_Pattern CORBA class in order to treat Notebook
+#  variables in some methods
 #
 class Pattern(SMESH._objref_SMESH_Pattern):
 
@@ -5128,12 +5225,13 @@ omniORB.registerObjref(SMESH._objref_SMESH_Pattern._NP_RepositoryId, Pattern)
 ## Private class used to bind methods creating algorithms to the class Mesh
 #
 class algoCreator:
-    def __init__(self):
+    def __init__(self, method):
         self.mesh = None
         self.defaultAlgoType = ""
         self.algoTypeToClass = {}
+        self.method = method
 
-    # Stores a python class of algorithm
+    # Store a python class of algorithm
     def add(self, algoClass):
         if type( algoClass ).__name__ == 'classobj' and \
            hasattr( algoClass, "algoType"):
@@ -5143,27 +5241,50 @@ class algoCreator:
                 self.defaultAlgoType = algoClass.algoType
             #print "Add",algoClass.algoType, "dflt",self.defaultAlgoType
 
-    # creates a copy of self and assign mesh to the copy
+    # Create a copy of self and assign mesh to the copy
     def copy(self, mesh):
-        other = algoCreator()
+        other = algoCreator( self.method )
         other.defaultAlgoType = self.defaultAlgoType
-        other.algoTypeToClass  = self.algoTypeToClass
+        other.algoTypeToClass = self.algoTypeToClass
         other.mesh = mesh
         return other
 
-    # creates an instance of algorithm
+    # Create an instance of algorithm
     def __call__(self,algo="",geom=0,*args):
-        algoType = self.defaultAlgoType
-        for arg in args + (algo,geom):
-            if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ):
-                geom = arg
-            if isinstance( arg, str ) and arg:
+        algoType = ""
+        shape = 0
+        if isinstance( algo, str ):
+            algoType = algo
+        elif ( isinstance( algo, geomBuilder.GEOM._objref_GEOM_Object ) and \
+               not isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object )):
+            shape = algo
+        elif algo:
+            args += (algo,)
+
+        if isinstance( geom, geomBuilder.GEOM._objref_GEOM_Object ):
+            shape = geom
+        elif not algoType and isinstance( geom, str ):
+            algoType = geom
+        elif geom:
+            args += (geom,)
+        for arg in args:
+            if isinstance( arg, geomBuilder.GEOM._objref_GEOM_Object ) and not shape:
+                shape = arg
+            elif isinstance( arg, str ) and not algoType:
                 algoType = arg
+            else:
+                import traceback, sys
+                msg = "Warning. Unexpected argument in mesh.%s() --->  %s" % ( self.method, arg )
+                sys.stderr.write( msg + '\n' )
+                tb = traceback.extract_stack(None,2)
+                traceback.print_list( [tb[0]] )
+        if not algoType:
+            algoType = self.defaultAlgoType
         if not algoType and self.algoTypeToClass:
             algoType = self.algoTypeToClass.keys()[0]
         if self.algoTypeToClass.has_key( algoType ):
             #print "Create algo",algoType
-            return self.algoTypeToClass[ algoType ]( self.mesh, geom )
+            return self.algoTypeToClass[ algoType ]( self.mesh, shape )
         raise RuntimeError, "No class found for algo type %s" % algoType
         return None
 
@@ -5198,7 +5319,7 @@ class hypMethodWrapper:
         return result
     pass
 
-## A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+## A helper class that calls UnRegister() of SALOME.GenericObj'es stored in it
 #
 class genObjUnRegister:
 
@@ -5245,7 +5366,7 @@ for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
         if type( algo ).__name__ == 'classobj' and hasattr( algo, "meshMethod" ):
             #print "                     meshMethod:" , str(algo.meshMethod)
             if not hasattr( Mesh, algo.meshMethod ):
-                setattr( Mesh, algo.meshMethod, algoCreator()
+                setattr( Mesh, algo.meshMethod, algoCreator( algo.meshMethod ))
                 pass
             getattr( Mesh, algo.meshMethod ).add( algo )
             pass