Salome HOME
Issue 0020755: EDF 1279 MESH : 'Mesh to Pass Through a Point' enhancement
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index 428aacbc94226da6a95b418ae3270d0fb4d239d8..bde96521a47bca088cf764a9a4f17885df167d23 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
 //  File   : SMESH_MeshEditor_i.cxx
 //  Author : Nicolas REJNERI
 //  Module : SMESH
-
+//
 #include "SMESH_MeshEditor_i.hxx"
 
 #include "SMDS_Mesh0DElement.hxx"
@@ -149,24 +150,26 @@ namespace {
     }
   };// struct TPreviewMesh
 
-  static SMESH_NodeSearcher * myNodeSearcher = 0;
+  static SMESH_NodeSearcher *    theNodeSearcher    = 0;
+  static SMESH_ElementSearcher * theElementSearcher = 0;
 
   //=============================================================================
   /*!
-   * \brief Deleter of myNodeSearcher at any compute event occured
+   * \brief Deleter of theNodeSearcher at any compute event occured
    */
   //=============================================================================
 
-  struct TNodeSearcherDeleter : public SMESH_subMeshEventListener
+  struct TSearchersDeleter : public SMESH_subMeshEventListener
   {
     SMESH_Mesh* myMesh;
     //!< Constructor
-    TNodeSearcherDeleter(): SMESH_subMeshEventListener( false ), // won't be deleted by submesh
-    myMesh(0) {}
-    //!< Delete myNodeSearcher
+    TSearchersDeleter(): SMESH_subMeshEventListener( false ), // won't be deleted by submesh
+                         myMesh(0) {}
+    //!< Delete theNodeSearcher
     static void Delete()
     {
-      if ( myNodeSearcher ) { delete myNodeSearcher; myNodeSearcher = 0; }
+      if ( theNodeSearcher )    delete theNodeSearcher;    theNodeSearcher    = 0;
+      if ( theElementSearcher ) delete theElementSearcher; theElementSearcher = 0;
     }
     typedef map < int, SMESH_subMesh * > TDependsOnMap;
     //!< The meshod called by submesh: do my main job
@@ -178,19 +181,22 @@ namespace {
         Unset( sm->GetFather() );
       }
     }
-    //!< set self on all submeshes and delete myNodeSearcher if other mesh is set
+    //!< set self on all submeshes and delete theNodeSearcher if other mesh is set
     void Set(SMESH_Mesh* mesh)
     {
-      if ( myMesh && myMesh != mesh ) {
-        Delete();
-        Unset( myMesh );
-      }
-      myMesh = mesh;
-      if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
-        const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
-        TDependsOnMap::const_iterator sm;
-        for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
-          sm->second->SetEventListener( this, 0, sm->second );
+      if ( myMesh != mesh )
+      {
+        if ( myMesh ) {
+          Delete();
+          Unset( myMesh );
+        }
+        myMesh = mesh;
+        if ( SMESH_subMesh* myMainSubMesh = mesh->GetSubMeshContaining(1) ) {
+          const TDependsOnMap & subMeshes = myMainSubMesh->DependsOn();
+          TDependsOnMap::const_iterator sm;
+          for (sm = subMeshes.begin(); sm != subMeshes.end(); sm++)
+            sm->second->SetEventListener( this, 0, sm->second );
+        }
       }
     }
     //!<  delete self from all submeshes
@@ -204,7 +210,8 @@ namespace {
       }
       myMesh = 0;
     }
-  };
+
+  } theSearchersDeleter;
 
   TCollection_AsciiString mirrorTypeName( SMESH::SMESH_MeshEditor::MirrorType theMirrorType )
   {
@@ -252,7 +259,7 @@ SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
  */
 //================================================================================
 
-void SMESH_MeshEditor_i::initData()
+void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 {
   if ( myPreviewMode ) {
     myPreviewData = new SMESH::MeshPreviewStruct();
@@ -260,10 +267,32 @@ void SMESH_MeshEditor_i::initData()
   else {
     myLastCreatedElems = new SMESH::long_array();
     myLastCreatedNodes = new SMESH::long_array();
-    TNodeSearcherDeleter::Delete();
+    if ( deleteSearchers )
+      TSearchersDeleter::Delete();
   }
 }
 
+//=======================================================================
+//function : MakeIDSource
+//purpose  : Wrap a sequence of ids in a SMESH_IDSource
+//=======================================================================
+
+struct _IDSource : public POA_SMESH::SMESH_IDSource
+{
+  SMESH::long_array _ids;
+  SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
+  SMESH::long_array* GetMeshInfo() { return 0; }
+};
+
+SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids)
+{
+  _IDSource* anIDSource = new _IDSource;
+  anIDSource->_ids = ids;
+  SMESH::SMESH_IDSource_var anIDSourceVar = anIDSource->_this();
+  
+  return anIDSourceVar._retn();
+}
+
 //=============================================================================
 /*!
  *
@@ -271,7 +300,7 @@ void SMESH_MeshEditor_i::initData()
 //=============================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
+SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
 {
   initData();
 
@@ -283,9 +312,10 @@ CORBA::Boolean
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".RemoveElements( " << IDsOfElements << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'RemoveElements: ', isDone";
-#endif
+
+  if ( IDsOfElements.length() )
+    myMesh->SetIsModified( true ); // issue 0020693
+
   // Remove Elements
   return anEditor.Remove( IdList, false );
 }
@@ -307,9 +337,9 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNo
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'RemoveNodes: ', isDone";
-#endif
+
+  if ( IDsOfNodes.length() )
+    myMesh->SetIsModified( true ); // issue 0020693
 
   return anEditor.Remove( IdList, true );
 }
@@ -331,6 +361,8 @@ CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
   TPythonDump() << "nodeID = " << this << ".AddNode( "
                 << x << ", " << y << ", " << z << " )";
 
+  myMesh->SetIsModified( true ); // issue 0020693
+
   return N->GetID();
 }
 
@@ -349,6 +381,8 @@ CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
   // Update Python script
   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
 
+  myMesh->SetIsModified( true ); // issue 0020693
+
   if (elem)
     return elem->GetID();
 
@@ -390,7 +424,7 @@ CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
   }
 
   if(elem)
-    return elem->GetID();
+    return myMesh->SetIsModified( true ), elem->GetID();
 
   return 0;
 }
@@ -430,12 +464,15 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
     elem = GetMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
                                 nodes[4], nodes[5], nodes[6], nodes[7]);
   }
+  else if (NbNodes > 2) {
+    elem = GetMeshDS()->AddPolygonalFace(nodes);
+  }
 
   // Update Python script
   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
 
   if(elem)
-    return elem->GetID();
+    return myMesh->SetIsModified( true ), elem->GetID();
 
   return 0;
 }
@@ -445,8 +482,7 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
  *  AddPolygonalFace
  */
 //=============================================================================
-CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace
-                                   (const SMESH::long_array & IDsOfNodes)
+CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
 {
   initData();
 
@@ -456,17 +492,11 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace
     nodes[i] = GetMeshDS()->FindNode(IDsOfNodes[i]);
 
   const SMDS_MeshElement* elem = GetMeshDS()->AddPolygonalFace(nodes);
-  
+
   // Update Python script
   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'AddPolygonalFace: ', faceID";
-#endif
-
-  if(elem)
-    return elem->GetID();
 
-  return 0;
+  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
 }
 
 //=============================================================================
@@ -508,12 +538,9 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
 
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'AddVolume: ', volID";
-#endif
 
   if(elem)
-    return elem->GetID();
+    return myMesh->SetIsModified( true ), elem->GetID();
 
   return 0;
 }
@@ -523,9 +550,8 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
  *  AddPolyhedralVolume
  */
 //=============================================================================
-CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
-                                   (const SMESH::long_array & IDsOfNodes,
-                                    const SMESH::long_array & Quantities)
+CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
+                                                     const SMESH::long_array & Quantities)
 {
   initData();
 
@@ -544,14 +570,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
                 << IDsOfNodes << ", " << Quantities << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
-#endif
-
-  if(elem)
-    return elem->GetID();
 
-  return 0;
+  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
 }
 
 //=============================================================================
@@ -559,8 +579,7 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume
  *  AddPolyhedralVolumeByFaces
  */
 //=============================================================================
-CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces
-                                   (const SMESH::long_array & IdsOfFaces)
+CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
 {
   initData();
 
@@ -583,14 +602,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
                 << IdsOfFaces << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'AddPolyhedralVolume: ', volID";
-#endif
-
-  if(elem)
-    return elem->GetID();
 
-  return 0;
+  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
 }
 
 //=============================================================================
@@ -620,6 +633,8 @@ void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexI
     THROW_SALOME_CORBA_EXCEPTION("Invalid VertexID", SALOME::BAD_PARAM);
 
   mesh->SetNodeOnVertex( node, VertexID );
+
+  myMesh->SetIsModified( true );
 }
 
 //=============================================================================
@@ -656,6 +671,8 @@ void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
     THROW_SALOME_CORBA_EXCEPTION("Invalid paramOnEdge", SALOME::BAD_PARAM);
 
   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
+
+  myMesh->SetIsModified( true );
 }
 
 //=============================================================================
@@ -696,15 +713,17 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
   if ( isOut ) {
 #ifdef _DEBUG_
     MESSAGE ( "FACE " << FaceID << " (" << u << "," << v << ") out of "
-           << " u( " <<  surf.FirstUParameter() 
-           << "," <<  surf.LastUParameter()  
-           << ") v( " <<  surf.FirstVParameter() 
-           << "," <<  surf.LastVParameter() << ")" );
+              << " u( " <<  surf.FirstUParameter() 
+              << "," <<  surf.LastUParameter()  
+              << ") v( " <<  surf.FirstVParameter() 
+              << "," <<  surf.LastVParameter() << ")" );
 #endif    
     THROW_SALOME_CORBA_EXCEPTION("Invalid UV", SALOME::BAD_PARAM);
   }
 
   mesh->SetNodeOnFace( node, FaceID, u, v );
+
+  myMesh->SetIsModified( true );
 }
 
 //=============================================================================
@@ -735,6 +754,8 @@ void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID
     THROW_SALOME_CORBA_EXCEPTION("Invalid SolidID", SALOME::BAD_PARAM);
 
   mesh->SetNodeInVolume( node, SolidID );
+
+  // myMesh->SetIsModified( true ); - SetNodeInVolume() can't prevent re-compute, I believe
 }
 
 //=============================================================================
@@ -768,33 +789,8 @@ void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
     THROW_SALOME_CORBA_EXCEPTION("Invalid shape type", SALOME::BAD_PARAM);
 
   mesh->SetMeshElementOnShape( elem, ShapeID );
-}
-
-
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-
-CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
-                                            CORBA::Double x,
-                                            CORBA::Double y,
-                                            CORBA::Double z)
-{
-  initData();
-
-  const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
-  if ( !node )
-    return false;
 
-  GetMeshDS()->MoveNode(node, x, y, z);
-
-  // Update Python script
-  TPythonDump() << "isDone = " << this << ".MoveNode( "
-                << NodeID << ", " << x << ", " << y << ", " << z << " )";
-
-  return true;
+  myMesh->SetIsModified( true );
 }
 
 //=============================================================================
@@ -817,6 +813,8 @@ CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
   TPythonDump() << "isDone = " << this << ".InverseDiag( "
                 << NodeID1 << ", " << NodeID2 << " )";
 
+  myMesh->SetIsModified( true );
+
   ::SMESH_MeshEditor aMeshEditor( myMesh );
   return aMeshEditor.InverseDiag ( n1, n2 );
 }
@@ -845,6 +843,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
 
   bool stat = aMeshEditor.DeleteDiag ( n1, n2 );
 
+  if ( stat )
+    myMesh->SetIsModified( true ); // issue 0020693
+    
   storeResult(aMeshEditor);
 
   return stat;
@@ -871,6 +872,9 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfEleme
   // Update Python script
   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
 
+  if ( IDsOfElements.length() )
+    myMesh->SetIsModified( true ); // issue 0020693
+
   return true;
 }
 
@@ -885,15 +889,13 @@ CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theO
 {
   initData();
 
+  TPythonDump aTPythonDump; // suppress dump in Reorient()
+
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = Reorient(anElementsId);
 
-  // Clear python line, created by Reorient()
-  SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".ReorientObject( " << theObject << " )";
+  aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
 
   return isDone;
 }
@@ -903,10 +905,10 @@ namespace
   //================================================================================
   /*!
    * \brief function for conversion long_array to TIDSortedElemSet
-    * \param IDs - array of IDs
-    * \param aMesh - mesh
-    * \param aMap - collection to fill
-    * \param aType - element type
+   * \param IDs - array of IDs
+   * \param aMesh - mesh
+   * \param aMap - collection to fill
+   * \param aType - element type
    */
   //================================================================================
 
@@ -917,7 +919,9 @@ namespace
   { 
     for (int i=0; i<IDs.length(); i++) {
       CORBA::Long ind = IDs[i];
-      const SMDS_MeshElement * elem = aMesh->FindElement(ind);
+      const SMDS_MeshElement * elem =
+        (aType == SMDSAbs_Node ? aMesh->FindNode(ind)
+         : aMesh->FindElement(ind));
       if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
         aMap.insert( elem );
     }
@@ -950,13 +954,12 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfE
   // Update Python script
   TPythonDump() << "isDone = " << this << ".TriToQuad( "
                 << IDsOfElements << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'TriToQuad: ', isDone";
-#endif
 
   ::SMESH_MeshEditor anEditor( myMesh );
 
   bool stat = anEditor.TriToQuad( faces, aCrit, MaxAngle );
+  if ( stat )
+    myMesh->SetIsModified( true ); // issue 0020693
 
   storeResult(anEditor);
 
@@ -975,25 +978,16 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr
 {
   initData();
 
+  TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
 
-  // Clear python line(s), created by TriToQuad()
-  SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#ifdef _DEBUG_
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#endif
-
   SMESH::NumericalFunctor_i* aNumericalFunctor =
     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
 
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".TriToQuadObject("
-                << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'TriToQuadObject: ', isDone";
-#endif
+  aTPythonDump << "isDone = " << this << ".TriToQuadObject("
+               << theObject << ", " << aNumericalFunctor << ", " << MaxAngle << " )";
 
   return isDone;
 }
@@ -1024,12 +1018,11 @@ CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfE
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'QuadToTri: ', isDone";
-#endif
 
   ::SMESH_MeshEditor anEditor( myMesh );
   CORBA::Boolean stat = anEditor.QuadToTri( faces, aCrit );
+  if ( stat )
+    myMesh->SetIsModified( true ); // issue 0020693
 
   storeResult(anEditor);
 
@@ -1047,24 +1040,16 @@ CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr
 {
   initData();
 
+  TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
+
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
 
-  // Clear python line(s), created by QuadToTri()
-  SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#ifdef _DEBUG_
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#endif
-
   SMESH::NumericalFunctor_i* aNumericalFunctor =
     SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
 
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'QuadToTriObject: ', isDone";
-#endif
+  aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
 
   return isDone;
 }
@@ -1087,12 +1072,12 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfEle
   // Update Python script
   TPythonDump() << "isDone = " << this << ".SplitQuad( "
                 << IDsOfElements << ", " << Diag13 << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'SplitQuad: ', isDone";
-#endif
 
   ::SMESH_MeshEditor anEditor( myMesh );
   CORBA::Boolean stat = anEditor.QuadToTri( faces, Diag13 );
+  if ( stat )
+    myMesh->SetIsModified( true ); // issue 0020693
+
 
   storeResult(anEditor);
 
@@ -1110,22 +1095,14 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr th
 {
   initData();
 
+  TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
+
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
 
-  // Clear python line(s), created by SplitQuad()
-  SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#ifdef _DEBUG_
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#endif
-
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".SplitQuadObject( "
-                << theObject << ", " << Diag13 << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'SplitQuadObject: ', isDone";
-#endif
+  aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
+               << theObject << ", " << Diag13 << " )";
 
   return isDone;
 }
@@ -1156,6 +1133,33 @@ CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
   return -1;
 }
 
+//================================================================================
+/*!
+ * \brief Split volumic elements into tetrahedrons
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
+                                                CORBA::Short              methodFlags)
+  throw (SALOME::SALOME_Exception)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+
+  SMESH::long_array_var anElementsId = elems->GetIDs();
+  TIDSortedElemSet elemSet;
+  arrayToSet( anElementsId, GetMeshDS(), elemSet, SMDSAbs_Volume );
+  
+  ::SMESH_MeshEditor anEditor (myMesh);
+  anEditor.SplitVolumesIntoTetra( elemSet, int( methodFlags ));
+
+  storeResult(anEditor);
+
+//   if ( myLastCreatedElems.length() ) - it does not influence Compute()
+//     myMesh->SetIsModified( true ); // issue 0020693
+
+  TPythonDump() << this << ".SplitVolumesIntoTetra( "
+                << elems << ", " << methodFlags << " )";
+}
 
 //=======================================================================
 //function : Smooth
@@ -1163,14 +1167,14 @@ CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
 //=======================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
-                             const SMESH::long_array &              IDsOfFixedNodes,
-                             CORBA::Long                            MaxNbOfIterations,
-                             CORBA::Double                          MaxAspectRatio,
-                             SMESH::SMESH_MeshEditor::Smooth_Method Method)
+SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
+                           const SMESH::long_array &              IDsOfFixedNodes,
+                           CORBA::Long                            MaxNbOfIterations,
+                           CORBA::Double                          MaxAspectRatio,
+                           SMESH::SMESH_MeshEditor::Smooth_Method Method)
 {
   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
-                MaxAspectRatio, Method, false );
+                 MaxAspectRatio, Method, false );
 }
 
 
@@ -1180,14 +1184,14 @@ CORBA::Boolean
 //=======================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
-                                       const SMESH::long_array &              IDsOfFixedNodes,
-                                       CORBA::Long                            MaxNbOfIterations,
-                                       CORBA::Double                          MaxAspectRatio,
-                                       SMESH::SMESH_MeshEditor::Smooth_Method Method)
+SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsOfElements,
+                                     const SMESH::long_array &              IDsOfFixedNodes,
+                                     CORBA::Long                            MaxNbOfIterations,
+                                     CORBA::Double                          MaxAspectRatio,
+                                     SMESH::SMESH_MeshEditor::Smooth_Method Method)
 {
   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
-                MaxAspectRatio, Method, true );
+                 MaxAspectRatio, Method, true );
 }
 
 
@@ -1197,11 +1201,11 @@ CORBA::Boolean
 //=======================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
-                                  const SMESH::long_array &              IDsOfFixedNodes,
-                                  CORBA::Long                            MaxNbOfIterations,
-                                  CORBA::Double                          MaxAspectRatio,
-                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
+SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObject,
+                                 const SMESH::long_array &              IDsOfFixedNodes,
+                                 CORBA::Long                            MaxNbOfIterations,
+                                 CORBA::Double                          MaxAspectRatio,
+                                 SMESH::SMESH_MeshEditor::Smooth_Method Method)
 {
   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
                        MaxAspectRatio, Method, false);
@@ -1214,11 +1218,11 @@ CORBA::Boolean
 //=======================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
-                                  const SMESH::long_array &              IDsOfFixedNodes,
-                                  CORBA::Long                            MaxNbOfIterations,
-                                  CORBA::Double                          MaxAspectRatio,
-                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
+SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr              theObject,
+                                           const SMESH::long_array &              IDsOfFixedNodes,
+                                           CORBA::Long                            MaxNbOfIterations,
+                                           CORBA::Double                          MaxAspectRatio,
+                                           SMESH::SMESH_MeshEditor::Smooth_Method Method)
 {
   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
                        MaxAspectRatio, Method, true);
@@ -1232,12 +1236,12 @@ CORBA::Boolean
 //=============================================================================
 
 CORBA::Boolean
-  SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
-                             const SMESH::long_array &              IDsOfFixedNodes,
-                             CORBA::Long                            MaxNbOfIterations,
-                             CORBA::Double                          MaxAspectRatio,
-                             SMESH::SMESH_MeshEditor::Smooth_Method Method,
-                             bool                                   IsParametric)
+SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
+                           const SMESH::long_array &              IDsOfFixedNodes,
+                           CORBA::Long                            MaxNbOfIterations,
+                           CORBA::Double                          MaxAspectRatio,
+                           SMESH::SMESH_MeshEditor::Smooth_Method Method,
+                           bool                                   IsParametric)
 {
   initData();
 
@@ -1261,6 +1265,8 @@ CORBA::Boolean
   anEditor.Smooth(elements, fixedNodes, method,
                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
 
+  myMesh->SetIsModified( true ); // issue 0020693
+
   storeResult(anEditor);
 
   // Update Python script
@@ -1271,9 +1277,6 @@ CORBA::Boolean
                 << "SMESH.SMESH_MeshEditor."
                 << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
-#ifdef _DEBUG_
-  TPythonDump() << "print 'Smooth: ', isDone";
-#endif
 
   return true;
 }
@@ -1295,28 +1298,20 @@ SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObjec
 {
   initData();
 
+  TPythonDump aTPythonDump;  // suppress dump in smooth()
+
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
                                   MaxAspectRatio, Method, IsParametric);
 
-  // Clear python line(s), created by Smooth()
-  SMESH_Gen_i* aSMESHGen = SMESH_Gen_i::GetSMESHGen();
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#ifdef _DEBUG_
-  aSMESHGen->RemoveLastFromPythonScript(aSMESHGen->GetCurrentStudyID());
-#endif
-
   // Update Python script
-  TPythonDump() << "isDone = " << this << "."
-                << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
-                << theObject << ", " << IDsOfFixedNodes << ", "
-                << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
-                << "SMESH.SMESH_MeshEditor."
-                << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
-                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
-#ifdef _DEBUG_
-  TPythonDump() << "print 'SmoothObject: ', isDone";
-#endif
+  aTPythonDump << "isDone = " << this << "."
+               << (IsParametric ? "SmoothParametricObject( " : "SmoothObject( ")
+               << theObject << ", " << IDsOfFixedNodes << ", "
+               << MaxNbOfIterations << ", " << MaxAspectRatio << ", "
+               << "SMESH.SMESH_MeshEditor."
+               << ( Method == SMESH::SMESH_MeshEditor::CENTROIDAL_SMOOTH ?
+                    "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
 
   return isDone;
 }
@@ -1352,9 +1347,9 @@ void SMESH_MeshEditor_i::RenumberElements()
 }
 
 //=======================================================================
-  /*!
  * \brief Return groups by their IDs
  */
+/*!
+ * \brief Return groups by their IDs
+ */
 //=======================================================================
 
 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
@@ -1377,7 +1372,7 @@ SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
                                   CORBA::Long               theNbOfSteps,
                                   CORBA::Double             theTolerance,
                                   const bool                theMakeGroups,
-                                 const SMDSAbs_ElementType theElementType)
+                                  const SMDSAbs_ElementType theElementType)
 {
   initData();
 
@@ -1406,10 +1401,12 @@ SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
 
   ::SMESH_MeshEditor anEditor( mesh );
   ::SMESH_MeshEditor::PGroupIDs groupIds =
-    anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
-                            theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
+      anEditor.RotationSweep (*workElements, Ax1, theAngleInRadians,
+                              theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
   storeResult(anEditor);
 
+  //  myMesh->SetIsModified( true ); -- it does not influence Compute()
+
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 }
 
@@ -1477,10 +1474,10 @@ SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfEle
 //=======================================================================
 
 void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
-                                            const SMESH::AxisStruct & theAxis,
-                                            CORBA::Double             theAngleInRadians,
-                                            CORBA::Long               theNbOfSteps,
-                                            CORBA::Double             theTolerance)
+                                             const SMESH::AxisStruct & theAxis,
+                                             CORBA::Double             theAngleInRadians,
+                                             CORBA::Long               theNbOfSteps,
+                                             CORBA::Double             theTolerance)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".RotationSweepObject( "
@@ -1505,10 +1502,10 @@ void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject
 //=======================================================================
 
 void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
-                                              const SMESH::AxisStruct & theAxis,
-                                              CORBA::Double             theAngleInRadians,
-                                              CORBA::Long               theNbOfSteps,
-                                              CORBA::Double             theTolerance)
+                                               const SMESH::AxisStruct & theAxis,
+                                               CORBA::Double             theAngleInRadians,
+                                               CORBA::Long               theNbOfSteps,
+                                               CORBA::Double             theTolerance)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".RotationSweepObject1D( "
@@ -1525,7 +1522,7 @@ void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObje
                 theNbOfSteps,
                 theTolerance,
                 false,
-               SMDSAbs_Edge);
+                SMDSAbs_Edge);
 }
 
 //=======================================================================
@@ -1534,10 +1531,10 @@ void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObje
 //=======================================================================
 
 void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
-                                              const SMESH::AxisStruct & theAxis,
-                                              CORBA::Double             theAngleInRadians,
-                                              CORBA::Long               theNbOfSteps,
-                                              CORBA::Double             theTolerance)
+                                               const SMESH::AxisStruct & theAxis,
+                                               CORBA::Double             theAngleInRadians,
+                                               CORBA::Long               theNbOfSteps,
+                                               CORBA::Double             theTolerance)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".RotationSweepObject2D( "
@@ -1554,7 +1551,7 @@ void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObje
                 theNbOfSteps,
                 theTolerance,
                 false,
-               SMDSAbs_Face);
+                SMDSAbs_Face);
 }
 
 //=======================================================================
@@ -1581,7 +1578,7 @@ SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theO
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump<< this << ".RotationSweepObjectMakeGroups( "
                << theObject << ", "
-              << theAxis << ", "
+               << theAxis << ", "
                << theAngleInRadians << ", "
                << theNbOfSteps << ", "
                << theTolerance << " )";
@@ -1596,10 +1593,10 @@ SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theO
 
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                   const SMESH::AxisStruct&  theAxis,
-                                                   CORBA::Double             theAngleInRadians,
-                                                   CORBA::Long               theNbOfSteps,
-                                                   CORBA::Double             theTolerance)
+                                                    const SMESH::AxisStruct&  theAxis,
+                                                    CORBA::Double             theAngleInRadians,
+                                                    CORBA::Long               theNbOfSteps,
+                                                    CORBA::Double             theTolerance)
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
@@ -1608,13 +1605,13 @@ SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr th
                                                theNbOfSteps,
                                                theTolerance,
                                                true,
-                                              SMDSAbs_Edge);
+                                               SMDSAbs_Edge);
   if ( !myPreviewMode ) {
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump<< this << ".RotationSweepObject1DMakeGroups( "
                << theObject << ", "
-              << theAxis << ", "
+               << theAxis << ", "
                << theAngleInRadians << ", "
                << theNbOfSteps << ", "
                << theTolerance << " )";
@@ -1629,10 +1626,10 @@ SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr th
 
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                   const SMESH::AxisStruct&  theAxis,
-                                                   CORBA::Double             theAngleInRadians,
-                                                   CORBA::Long               theNbOfSteps,
-                                                   CORBA::Double             theTolerance)
+                                                    const SMESH::AxisStruct&  theAxis,
+                                                    CORBA::Double             theAngleInRadians,
+                                                    CORBA::Long               theNbOfSteps,
+                                                    CORBA::Double             theTolerance)
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
@@ -1641,13 +1638,13 @@ SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr th
                                                theNbOfSteps,
                                                theTolerance,
                                                true,
-                                              SMDSAbs_Face);
+                                               SMDSAbs_Face);
   if ( !myPreviewMode ) {
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump<< this << ".RotationSweepObject2DMakeGroups( "
                << theObject << ", "
-              << theAxis << ", "
+               << theAxis << ", "
                << theAngleInRadians << ", "
                << theNbOfSteps << ", "
                << theTolerance << " )";
@@ -1719,8 +1716,8 @@ void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElemen
 //=======================================================================
 
 void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
-                                             const SMESH::DirStruct &  theStepVector,
-                                             CORBA::Long               theNbOfSteps)
+                                              const SMESH::DirStruct &  theStepVector,
+                                              CORBA::Long               theNbOfSteps)
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
@@ -1775,7 +1772,7 @@ SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfEl
                                              CORBA::Long              theNbOfSteps)
 {
   SMESH::ListOfGroups* aGroups = extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, true );
-    
+
   if ( !myPreviewMode ) {
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
@@ -1796,7 +1793,7 @@ SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr the
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups * aGroups = extrusionSweep (anElementsId, theStepVector, theNbOfSteps, true );
-  
+
   if ( !myPreviewMode ) {
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
@@ -1822,7 +1819,7 @@ SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr t
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( "
-               << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
+                << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
   }
   return aGroups;
 }
@@ -1843,7 +1840,7 @@ SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr t
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( "
-               << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
+                << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
   }
   return aGroups;
 }
@@ -1886,10 +1883,10 @@ SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements
 //=======================================================================
 
 void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
-                                          const SMESH::DirStruct &  theStepVector,
-                                          CORBA::Long               theNbOfSteps,
-                                          CORBA::Long               theExtrFlags,
-                                          CORBA::Double             theSewTolerance)
+                                           const SMESH::DirStruct &  theStepVector,
+                                           CORBA::Long               theNbOfSteps,
+                                           CORBA::Long               theExtrFlags,
+                                           CORBA::Double             theSewTolerance)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << "stepVector = " << theStepVector;
@@ -1921,12 +1918,12 @@ SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsO
                                                 CORBA::Double            theSewTolerance)
 {
   SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
-                                                    theStepVector,
-                                                    theNbOfSteps,
-                                                    theExtrFlags,
-                                                    theSewTolerance,
-                                                    true);
-  
+                                                     theStepVector,
+                                                     theNbOfSteps,
+                                                     theExtrFlags,
+                                                     theSewTolerance,
+                                                     true);
+
   if ( !myPreviewMode ) {
     TPythonDump() << "stepVector = " << theStepVector;
     TPythonDump aPythonDump;
@@ -1953,13 +1950,13 @@ SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsO
 static SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( const::SMESH_MeshEditor::Extrusion_Error e )
 {
   switch ( e ) {
-  RETCASE( EXTR_OK );
-  RETCASE( EXTR_NO_ELEMENTS );
-  RETCASE( EXTR_PATH_NOT_EDGE );
-  RETCASE( EXTR_BAD_PATH_SHAPE );
-  RETCASE( EXTR_BAD_STARTING_NODE );
-  RETCASE( EXTR_BAD_ANGLES_NUMBER );
-  RETCASE( EXTR_CANT_GET_TANGENT );
+    RETCASE( EXTR_OK );
+    RETCASE( EXTR_NO_ELEMENTS );
+    RETCASE( EXTR_PATH_NOT_EDGE );
+    RETCASE( EXTR_BAD_PATH_SHAPE );
+    RETCASE( EXTR_BAD_STARTING_NODE );
+    RETCASE( EXTR_BAD_ANGLES_NUMBER );
+    RETCASE( EXTR_CANT_GET_TANGENT );
   }
   return SMESH::SMESH_MeshEditor::EXTR_OK;
 }
@@ -1981,7 +1978,7 @@ SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfEleme
                                        const SMESH::PointStruct &  theRefPoint,
                                        const bool                  theMakeGroups,
                                        SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
-                                      const SMDSAbs_ElementType   theElementType)
+                                       const SMDSAbs_ElementType   theElementType)
 {
   initData();
 
@@ -2043,16 +2040,16 @@ SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfEleme
 
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements,
-                                       SMESH::SMESH_IDSource_ptr  Path,
-                                       CORBA::Long                NodeStart,
-                                       CORBA::Boolean             HasAngles,
-                                       const SMESH::double_array& Angles,
-                                       CORBA::Boolean             LinearVariation,
-                                       CORBA::Boolean             HasRefPoint,
-                                       const SMESH::PointStruct&  RefPoint,
-                                       const bool                 MakeGroups,
-                                       const SMDSAbs_ElementType  ElementType,
-                                       SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
+                                        SMESH::SMESH_IDSource_ptr  Path,
+                                        CORBA::Long                NodeStart,
+                                        CORBA::Boolean             HasAngles,
+                                        const SMESH::double_array& Angles,
+                                        CORBA::Boolean             LinearVariation,
+                                        CORBA::Boolean             HasRefPoint,
+                                        const SMESH::PointStruct&  RefPoint,
+                                        const bool                 MakeGroups,
+                                        const SMDSAbs_ElementType  ElementType,
+                                        SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
 {
   SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
 
@@ -2086,8 +2083,8 @@ SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements
       return EmptyGr;
     }
     error = anEditor.ExtrusionAlongTrack( elements, &(aMeshImp->GetImpl()), aNodeStart,
-                                         HasAngles, angles, LinearVariation,
-                                         HasRefPoint, refPnt, MakeGroups );
+                                          HasAngles, angles, LinearVariation,
+                                          HasRefPoint, refPnt, MakeGroups );
   }
   else {
     SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path );
@@ -2096,26 +2093,26 @@ SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements
       SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
       aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
       SMDS_MeshNode* aNodeStart = 
-       (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
+        (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
       if ( !aNodeStart ) {
-       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
-       return EmptyGr;
+        Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
+        return EmptyGr;
       }
       SMESH_subMesh* aSubMesh = 
-       aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
+        aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
       error = anEditor.ExtrusionAlongTrack( elements, aSubMesh, aNodeStart,
-                                           HasAngles, angles, LinearVariation,
-                                           HasRefPoint, refPnt, MakeGroups );
+                                            HasAngles, angles, LinearVariation,
+                                            HasRefPoint, refPnt, MakeGroups );
     }
     else {
       SMESH_Group_i* aGroupImp = SMESH::DownCast<SMESH_Group_i*>( Path );
       if(aGroupImp) {
-       // path as group of 1D elements
+        // path as group of 1D elements
       }
       else {
-       // invalid path
-       Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-       return EmptyGr;
+        // invalid path
+        Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
+        return EmptyGr;
       }
     }
   }
@@ -2140,14 +2137,14 @@ SMESH_MeshEditor_i::extrusionAlongPathX(const SMESH::long_array &  IDsOfElements
 //=======================================================================
 
 SMESH::SMESH_MeshEditor::Extrusion_Error
-  SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
-                                        SMESH::SMESH_Mesh_ptr       thePathMesh,
-                                        GEOM::GEOM_Object_ptr       thePathShape,
-                                        CORBA::Long                 theNodeStart,
-                                        CORBA::Boolean              theHasAngles,
-                                        const SMESH::double_array & theAngles,
-                                        CORBA::Boolean              theHasRefPoint,
-                                        const SMESH::PointStruct &  theRefPoint)
+SMESH_MeshEditor_i::ExtrusionAlongPath(const SMESH::long_array &   theIDsOfElements,
+                                       SMESH::SMESH_Mesh_ptr       thePathMesh,
+                                       GEOM::GEOM_Object_ptr       thePathShape,
+                                       CORBA::Long                 theNodeStart,
+                                       CORBA::Boolean              theHasAngles,
+                                       const SMESH::double_array & theAngles,
+                                       CORBA::Boolean              theHasRefPoint,
+                                       const SMESH::PointStruct &  theRefPoint)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
@@ -2228,13 +2225,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObject(SMESH::SMESH_IDSource_ptr   theObje
 
 SMESH::SMESH_MeshEditor::Extrusion_Error
 SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theObject,
-                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
-                                              GEOM::GEOM_Object_ptr       thePathShape,
-                                              CORBA::Long                 theNodeStart,
-                                              CORBA::Boolean              theHasAngles,
-                                              const SMESH::double_array & theAngles,
-                                              CORBA::Boolean              theHasRefPoint,
-                                              const SMESH::PointStruct &  theRefPoint)
+                                               SMESH::SMESH_Mesh_ptr       thePathMesh,
+                                               GEOM::GEOM_Object_ptr       thePathShape,
+                                               CORBA::Long                 theNodeStart,
+                                               CORBA::Boolean              theHasAngles,
+                                               const SMESH::double_array & theAngles,
+                                               CORBA::Boolean              theHasRefPoint,
+                                               const SMESH::PointStruct &  theRefPoint)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
@@ -2262,7 +2259,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theOb
                       theRefPoint,
                       false,
                       anError,
-                     SMDSAbs_Edge);
+                      SMDSAbs_Edge);
   return anError;
 }
 
@@ -2273,13 +2270,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObject1D(SMESH::SMESH_IDSource_ptr   theOb
 
 SMESH::SMESH_MeshEditor::Extrusion_Error
 SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theObject,
-                                              SMESH::SMESH_Mesh_ptr       thePathMesh,
-                                              GEOM::GEOM_Object_ptr       thePathShape,
-                                              CORBA::Long                 theNodeStart,
-                                              CORBA::Boolean              theHasAngles,
-                                              const SMESH::double_array & theAngles,
-                                              CORBA::Boolean              theHasRefPoint,
-                                              const SMESH::PointStruct &  theRefPoint)
+                                               SMESH::SMESH_Mesh_ptr       thePathMesh,
+                                               GEOM::GEOM_Object_ptr       thePathShape,
+                                               CORBA::Long                 theNodeStart,
+                                               CORBA::Boolean              theHasAngles,
+                                               const SMESH::double_array & theAngles,
+                                               CORBA::Boolean              theHasRefPoint,
+                                               const SMESH::PointStruct &  theRefPoint)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
@@ -2307,7 +2304,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObject2D(SMESH::SMESH_IDSource_ptr   theOb
                       theRefPoint,
                       false,
                       anError,
-                     SMDSAbs_Face);
+                      SMDSAbs_Face);
   return anError;
 }
 
@@ -2328,16 +2325,16 @@ SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theI
                                                  const SMESH::PointStruct&  theRefPoint,
                                                  SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
 {
-    SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
-                                                         thePathMesh,
-                                                         thePathShape,
-                                                         theNodeStart,
-                                                         theHasAngles,
-                                                         theAngles,
-                                                         theHasRefPoint,
-                                                         theRefPoint,
-                                                         true,
-                                                         Error);
+  SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
+                                                       thePathMesh,
+                                                       thePathShape,
+                                                       theNodeStart,
+                                                       theHasAngles,
+                                                       theAngles,
+                                                       theHasRefPoint,
+                                                       theRefPoint,
+                                                       true,
+                                                       Error);
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2348,7 +2345,7 @@ SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(const SMESH::long_array&   theI
       aPythonDump << ", error)";
     else
       aPythonDump <<"error";
-    
+
     aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
                << theIDsOfElements << ", "
                << thePathMesh      << ", "
@@ -2392,7 +2389,7 @@ ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                                                       theRefPoint,
                                                       true,
                                                       Error);
-  
+
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2411,11 +2408,11 @@ ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                 << theNodeStart     << ", "
                 << theHasAngles     << ", "
                 << theAngles        << ", "
-               << theHasRefPoint   << ", "
-               << "SMESH.PointStruct( "
-               << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
+                << theHasRefPoint   << ", "
+                << "SMESH.PointStruct( "
+                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
   }
   return aGroups;
 }
@@ -2427,14 +2424,14 @@ ExtrusionAlongPathObjectMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
 
 SMESH::ListOfGroups* SMESH_MeshEditor_i::
 ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
-                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
-                                    GEOM::GEOM_Object_ptr      thePathShape,
-                                    CORBA::Long                theNodeStart,
-                                    CORBA::Boolean             theHasAngles,
-                                    const SMESH::double_array& theAngles,
-                                    CORBA::Boolean             theHasRefPoint,
-                                    const SMESH::PointStruct&  theRefPoint,
-                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
+                                     SMESH::SMESH_Mesh_ptr      thePathMesh,
+                                     GEOM::GEOM_Object_ptr      thePathShape,
+                                     CORBA::Long                theNodeStart,
+                                     CORBA::Boolean             theHasAngles,
+                                     const SMESH::double_array& theAngles,
+                                     CORBA::Boolean             theHasRefPoint,
+                                     const SMESH::PointStruct&  theRefPoint,
+                                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
@@ -2447,8 +2444,8 @@ ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                                                       theRefPoint,
                                                       true,
                                                       Error,
-                                                     SMDSAbs_Edge);
-  
+                                                      SMDSAbs_Edge);
+
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2467,11 +2464,11 @@ ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                 << theNodeStart     << ", "
                 << theHasAngles     << ", "
                 << theAngles        << ", "
-               << theHasRefPoint   << ", "
-               << "SMESH.PointStruct( "
-               << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
+                << theHasRefPoint   << ", "
+                << "SMESH.PointStruct( "
+                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
   }
   return aGroups;
 }
@@ -2483,14 +2480,14 @@ ExtrusionAlongPathObject1DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
 
 SMESH::ListOfGroups* SMESH_MeshEditor_i::
 ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
-                                    SMESH::SMESH_Mesh_ptr      thePathMesh,
-                                    GEOM::GEOM_Object_ptr      thePathShape,
-                                    CORBA::Long                theNodeStart,
-                                    CORBA::Boolean             theHasAngles,
-                                    const SMESH::double_array& theAngles,
-                                    CORBA::Boolean             theHasRefPoint,
-                                    const SMESH::PointStruct&  theRefPoint,
-                                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
+                                     SMESH::SMESH_Mesh_ptr      thePathMesh,
+                                     GEOM::GEOM_Object_ptr      thePathShape,
+                                     CORBA::Long                theNodeStart,
+                                     CORBA::Boolean             theHasAngles,
+                                     const SMESH::double_array& theAngles,
+                                     CORBA::Boolean             theHasRefPoint,
+                                     const SMESH::PointStruct&  theRefPoint,
+                                     SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
@@ -2503,8 +2500,8 @@ ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                                                       theRefPoint,
                                                       true,
                                                       Error,
-                                                     SMDSAbs_Face);
-  
+                                                      SMDSAbs_Face);
+
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2523,11 +2520,11 @@ ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                 << theNodeStart     << ", "
                 << theHasAngles     << ", "
                 << theAngles        << ", "
-               << theHasRefPoint   << ", "
-               << "SMESH.PointStruct( "
-               << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
+                << theHasRefPoint   << ", "
+                << "SMESH.PointStruct( "
+                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
   }
   return aGroups;
 }
@@ -2539,30 +2536,30 @@ ExtrusionAlongPathObject2DMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
 //=======================================================================
 SMESH::ListOfGroups* SMESH_MeshEditor_i::
 ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
-                      SMESH::SMESH_IDSource_ptr  Path,
-                      CORBA::Long                NodeStart,
-                      CORBA::Boolean             HasAngles,
-                      const SMESH::double_array& Angles,
-                      CORBA::Boolean             LinearVariation,
-                      CORBA::Boolean             HasRefPoint,
-                      const SMESH::PointStruct&  RefPoint,
-                      CORBA::Boolean             MakeGroups,
-                      SMESH::ElementType         ElemType,
-                      SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
+                       SMESH::SMESH_IDSource_ptr  Path,
+                       CORBA::Long                NodeStart,
+                       CORBA::Boolean             HasAngles,
+                       const SMESH::double_array& Angles,
+                       CORBA::Boolean             LinearVariation,
+                       CORBA::Boolean             HasRefPoint,
+                       const SMESH::PointStruct&  RefPoint,
+                       CORBA::Boolean             MakeGroups,
+                       SMESH::ElementType         ElemType,
+                       SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
 {
   SMESH::long_array_var anElementsId = Object->GetIDs();
   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
-                                                     Path,
-                                                     NodeStart,
-                                                     HasAngles,
-                                                     Angles,
-                                                     LinearVariation,
-                                                     HasRefPoint,
-                                                     RefPoint,
-                                                     MakeGroups,
-                                                     (SMDSAbs_ElementType)ElemType,
-                                                     Error);
-  
+                                                      Path,
+                                                      NodeStart,
+                                                      HasAngles,
+                                                      Angles,
+                                                      LinearVariation,
+                                                      HasRefPoint,
+                                                      RefPoint,
+                                                      MakeGroups,
+                                                      (SMDSAbs_ElementType)ElemType,
+                                                      Error);
+
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2580,13 +2577,14 @@ ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
                 << NodeStart   << ", "
                 << HasAngles   << ", "
                 << Angles      << ", "
-               << LinearVariation << ", "
-               << HasRefPoint << ", "
-               << "SMESH.PointStruct( "
-               << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
-               << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
-               << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
-               << ElemType << " )";
+                << LinearVariation << ", "
+                << HasRefPoint << ", "
+                << "SMESH.PointStruct( "
+                << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
+                << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
+                << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
+                << MakeGroups << ", "
+                << ElemType << " )";
   }
   return aGroups;
 }
@@ -2598,29 +2596,29 @@ ExtrusionAlongPathObjX(SMESH::SMESH_IDSource_ptr  Object,
 //=======================================================================
 SMESH::ListOfGroups* SMESH_MeshEditor_i::
 ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
-                   SMESH::SMESH_IDSource_ptr  Path,
-                   CORBA::Long                NodeStart,
-                   CORBA::Boolean             HasAngles,
-                   const SMESH::double_array& Angles,
-                   CORBA::Boolean             LinearVariation,
-                   CORBA::Boolean             HasRefPoint,
-                   const SMESH::PointStruct&  RefPoint,
-                   CORBA::Boolean             MakeGroups,
-                   SMESH::ElementType         ElemType,
-                   SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
+                    SMESH::SMESH_IDSource_ptr  Path,
+                    CORBA::Long                NodeStart,
+                    CORBA::Boolean             HasAngles,
+                    const SMESH::double_array& Angles,
+                    CORBA::Boolean             LinearVariation,
+                    CORBA::Boolean             HasRefPoint,
+                    const SMESH::PointStruct&  RefPoint,
+                    CORBA::Boolean             MakeGroups,
+                    SMESH::ElementType         ElemType,
+                    SMESH::SMESH_MeshEditor::Extrusion_Error& Error)
 {
   SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
-                                                     Path,
-                                                     NodeStart,
-                                                     HasAngles,
-                                                     Angles,
-                                                     LinearVariation,
-                                                     HasRefPoint,
-                                                     RefPoint,
-                                                     MakeGroups,
-                                                     (SMDSAbs_ElementType)ElemType,
-                                                     Error);
-  
+                                                      Path,
+                                                      NodeStart,
+                                                      HasAngles,
+                                                      Angles,
+                                                      LinearVariation,
+                                                      HasRefPoint,
+                                                      RefPoint,
+                                                      MakeGroups,
+                                                      (SMDSAbs_ElementType)ElemType,
+                                                      Error);
+
   if ( !myPreviewMode ) {
     bool isDumpGroups = aGroups && aGroups->length() > 0;
     TPythonDump aPythonDump;
@@ -2638,13 +2636,13 @@ ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
                 << NodeStart   << ", "
                 << HasAngles   << ", "
                 << Angles      << ", "
-               << LinearVariation << ", "
-               << HasRefPoint << ", "
-               << "SMESH.PointStruct( "
-               << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
-               << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
-               << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
-               << ElemType << " )";
+                << LinearVariation << ", "
+                << HasRefPoint << ", "
+                << "SMESH.PointStruct( "
+                << ( HasRefPoint ? RefPoint.x : 0 ) << ", "
+                << ( HasRefPoint ? RefPoint.y : 0 ) << ", "
+                << ( HasRefPoint ? RefPoint.z : 0 ) << " ), "
+                << ElemType << " )";
   }
   return aGroups;
 }
@@ -2654,10 +2652,10 @@ ExtrusionAlongPathX(const SMESH::long_array&   IDsOfElements,
 /*!
  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
  * of given angles along path steps
 * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
 *                which proceeds the extrusion
 * \param PathShape is shape(edge); as the mesh can be complex, the edge 
 *                 is used to define the sub-mesh for the path
+ * \param PathMesh mesh containing a 1D sub-mesh on the edge, along 
+ *                which proceeds the extrusion
+ * \param PathShape is shape(edge); as the mesh can be complex, the edge 
+ *                 is used to define the sub-mesh for the path
  */
 //================================================================================
 
@@ -2697,7 +2695,7 @@ SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMes
           int iP = int( angPrevFloor );
           double angPrevCeil = ceil(angPrev);
           angle = ( angPrevCeil - angPrev ) * theAngles[ iP ];
-          
+
           int iC = int( angCurFloor );
           if ( iC < nbAngles )
             angle += ( angCur - angCurFloor ) * theAngles[ iC ];
@@ -2759,9 +2757,11 @@ SMESH_MeshEditor_i::mirror(const SMESH::long_array &           theIDsOfElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if(theCopy) {
+  if(theCopy)
     storeResult(anEditor);
-  }
+  else
+    myMesh->SetIsModified( true );
+
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 }
 
@@ -2792,9 +2792,9 @@ void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElem
 //=======================================================================
 
 void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObject,
-                                     const SMESH::AxisStruct &           theAxis,
-                                     SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
-                                     CORBA::Boolean                      theCopy)
+                                      const SMESH::AxisStruct &           theAxis,
+                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
+                                      CORBA::Boolean                      theCopy)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".MirrorObject( "
@@ -2868,7 +2868,7 @@ SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfE
   SMESH::SMESH_Mesh_var mesh;
   { // open new scope to dump "MakeMesh" command
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
-    
+
     TPythonDump pydump; // to prevent dump at mesh creation
 
     mesh = makeMesh( theMeshName );
@@ -2878,7 +2878,7 @@ SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfE
              false, theCopyGroups, & mesh_i->GetImpl());
       mesh_i->CreateGroupServants();
     }
-    
+
     if ( !myPreviewMode ) {
       pydump << mesh << " = " << this << ".MirrorMakeMesh( "
              << theIDsOfElements << ", "
@@ -2892,7 +2892,7 @@ SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfE
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
@@ -2912,7 +2912,7 @@ SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           the
   SMESH::SMESH_Mesh_var mesh;
   { // open new scope to dump "MakeMesh" command
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
-    
+
     TPythonDump pydump; // to prevent dump at mesh creation
 
     mesh = makeMesh( theMeshName );
@@ -2937,7 +2937,7 @@ SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           the
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
@@ -2968,6 +2968,8 @@ SMESH_MeshEditor_i::translate(const SMESH::long_array & theIDsOfElements,
 
   if(theCopy)
     storeResult(anEditor);
+  else
+    myMesh->SetIsModified( true );
 
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 }
@@ -2999,8 +3001,8 @@ void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
 //=======================================================================
 
 void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
-                                        const SMESH::DirStruct &  theVector,
-                                        CORBA::Boolean            theCopy)
+                                         const SMESH::DirStruct &  theVector,
+                                         CORBA::Boolean            theCopy)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".TranslateObject( "
@@ -3046,7 +3048,7 @@ SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObjec
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups * aGroups = translate(anElementsId, theVector, true, true);
-  
+
   if ( !myPreviewMode ) {
 
     TPythonDump aPythonDump;
@@ -3071,21 +3073,21 @@ SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
 {
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
-  
+
   { // open new scope to dump "MakeMesh" command
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
 
     TPythonDump pydump; // to prevent dump at mesh creation
-    
+
     mesh = makeMesh( theMeshName );
     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
-    
+
     if ( mesh_i ) {
       translate(theIDsOfElements, theVector,
                 false, theCopyGroups, & mesh_i->GetImpl());
       mesh_i->CreateGroupServants();
     }
-    
+
     if ( !myPreviewMode ) {
       pydump << mesh << " = " << this << ".TranslateMakeMesh( "
              << theIDsOfElements << ", "
@@ -3094,11 +3096,11 @@ SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
              << theMeshName << "' )";
     }
   }
-  
+
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
@@ -3117,11 +3119,11 @@ SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
   SMESH::SMESH_Mesh_var mesh;
   { // open new scope to dump "MakeMesh" command
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
-    
+
     TPythonDump pydump; // to prevent dump at mesh creation
     mesh = makeMesh( theMeshName );
     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
-    
+
     if ( mesh_i ) {
       SMESH::long_array_var anElementsId = theObject->GetIDs();
       translate(anElementsId, theVector,
@@ -3136,11 +3138,11 @@ SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
              << theMeshName << "' )";
     }
   }
-  
+
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
@@ -3172,9 +3174,11 @@ SMESH_MeshEditor_i::rotate(const SMESH::long_array & theIDsOfElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       anEditor.Transform (elements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if(theCopy) {
+  if(theCopy) 
     storeResult(anEditor);
-  }
+  else
+    myMesh->SetIsModified( true );
+
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 }
 
@@ -3208,9 +3212,9 @@ void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
 //=======================================================================
 
 void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
-                                     const SMESH::AxisStruct & theAxis,
-                                     CORBA::Double             theAngle,
-                                     CORBA::Boolean            theCopy)
+                                      const SMESH::AxisStruct & theAxis,
+                                      CORBA::Double             theAngle,
+                                      CORBA::Boolean            theCopy)
 {
   if ( !myPreviewMode ) {
     TPythonDump() << this << ".RotateObject( "
@@ -3243,7 +3247,7 @@ SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump << this << ".RotateMakeGroups( "
                 << theIDsOfElements << ", "
-               << theAxis << ", "
+                << theAxis << ", "
                 << theAngle << " )";
   }
   return aGroups;
@@ -3261,14 +3265,14 @@ SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
 {
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   SMESH::ListOfGroups * aGroups =  rotate(anElementsId,theAxis,theAngle,true,true);
+
   if ( !myPreviewMode ) {
     TPythonDump aPythonDump;
     DumpGroupsList(aPythonDump,aGroups);
     aPythonDump << this << ".RotateObjectMakeGroups( "
-               << theObject << ", "
-               << theAxis << ", "
-               << theAngle << " )";
+                << theObject << ", "
+                << theAxis << ", "
+                << theAngle << " )";
   }
   return aGroups;
 }
@@ -3290,12 +3294,12 @@ SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
 
   { // open new scope to dump "MakeMesh" command
     // and then "GetGroups" using SMESH_Mesh::GetGroups()
-    
+
     TPythonDump pydump; // to prevent dump at mesh creation
 
     mesh = makeMesh( theMeshName );
     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
-    
+
     if ( mesh_i ) {
       rotate(theIDsOfElements, theAxis, theAngleInRadians,
              false, theCopyGroups, & mesh_i->GetImpl());
@@ -3310,11 +3314,11 @@ SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
              << theMeshName << "' )";
     }
   }
-  
+
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
@@ -3332,14 +3336,14 @@ SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
 {
   SMESH::SMESH_Mesh_var mesh;
   SMESH_Mesh_i* mesh_i;
-  
+
   {// open new scope to dump "MakeMesh" command
    // and then "GetGroups" using SMESH_Mesh::GetGroups()
-    
+
     TPythonDump pydump; // to prevent dump at mesh creation
     mesh = makeMesh( theMeshName );
     mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
-    
+
     if (mesh_i ) {
       SMESH::long_array_var anElementsId = theObject->GetIDs();
       rotate(anElementsId, theAxis, theAngleInRadians,
@@ -3355,30 +3359,166 @@ SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
              << theMeshName << "' )";
     }
   }
-  
+
   //dump "GetGroups"
   if(!myPreviewMode && mesh_i)
     mesh_i->GetGroups();
-  
+
   return mesh._retn();
 }
 
+
 //=======================================================================
-//function : FindCoincidentNodes
-//purpose  :
+//function : scale
+//purpose  : 
 //=======================================================================
 
-void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
-                                              SMESH::array_of_long_array_out GroupsOfNodes)
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::scale(const SMESH::long_array &  theIDsOfElements,
+                          const SMESH::PointStruct&  thePoint,
+                          const SMESH::double_array& theScaleFact,
+                          CORBA::Boolean             theCopy,
+                          const bool                 theMakeGroups,
+                          ::SMESH_Mesh*              theTargetMesh)
 {
   initData();
 
-  ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
-  ::SMESH_MeshEditor anEditor( myMesh );
-  set<const SMDS_MeshNode*> nodes; // no input nodes
-  anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
+  TIDSortedElemSet elements;
+  arrayToSet(theIDsOfElements, GetMeshDS(), elements);
 
-  GroupsOfNodes = new SMESH::array_of_long_array;
+  gp_Pnt aPnt( thePoint.x, thePoint.y, thePoint.z );
+  list<double> aScaleFact;
+  for (int i = 0; i < theScaleFact.length(); i++) {
+    aScaleFact.push_back( theScaleFact[i] );
+  }
+
+  ::SMESH_MeshEditor anEditor( myMesh );
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      anEditor.Scale (elements, aPnt, aScaleFact, theCopy,
+                      theMakeGroups, theTargetMesh);
+
+  if(theCopy)
+    storeResult(anEditor);
+  else
+    myMesh->SetIsModified( true );
+
+  return theMakeGroups ? getGroups(groupIds.get()) : 0;
+}
+
+
+//=======================================================================
+//function : Scale
+//purpose  :
+//=======================================================================
+
+void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
+                               const SMESH::PointStruct&  thePoint,
+                               const SMESH::double_array& theScaleFact,
+                               CORBA::Boolean             theCopy)
+{
+  if ( !myPreviewMode ) {
+    TPythonDump() << this << ".Scale( "
+                  << theObject << ", "
+                  << "SMESH.PointStruct( "  << thePoint.x << ", "
+                  << thePoint.y << ", " << thePoint.z << " ) ,"
+                  << theScaleFact << ", "
+                  << theCopy << " )";
+  }
+  SMESH::long_array_var anElementsId = theObject->GetIDs();
+  scale(anElementsId, thePoint, theScaleFact, theCopy, false);
+}
+
+
+//=======================================================================
+//function : ScaleMakeGroups
+//purpose  : 
+//=======================================================================
+
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
+                                    const SMESH::PointStruct&  thePoint,
+                                    const SMESH::double_array& theScaleFact)
+{
+  SMESH::long_array_var anElementsId = theObject->GetIDs();
+  SMESH::ListOfGroups * aGroups = 
+    scale(anElementsId, thePoint, theScaleFact, true, true);
+
+  if ( !myPreviewMode ) {
+
+    TPythonDump aPythonDump;
+    DumpGroupsList(aPythonDump,aGroups);
+    aPythonDump << this << ".Scale("
+                << theObject << ","
+                << "SMESH.PointStruct(" <<thePoint.x << ","
+                << thePoint.y << "," << thePoint.z << "),"
+                << theScaleFact << ",True,True)";
+  }
+  return aGroups;
+}
+
+
+//=======================================================================
+//function : ScaleMakeMesh
+//purpose  : 
+//=======================================================================
+
+SMESH::SMESH_Mesh_ptr
+SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
+                                  const SMESH::PointStruct&  thePoint,
+                                  const SMESH::double_array& theScaleFact,
+                                  CORBA::Boolean             theCopyGroups,
+                                  const char*                theMeshName)
+{
+  SMESH_Mesh_i* mesh_i;
+  SMESH::SMESH_Mesh_var mesh;
+  { // open new scope to dump "MakeMesh" command
+    // and then "GetGroups" using SMESH_Mesh::GetGroups()
+
+    TPythonDump pydump; // to prevent dump at mesh creation
+    mesh = makeMesh( theMeshName );
+    mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+
+    if ( mesh_i ) {
+      SMESH::long_array_var anElementsId = theObject->GetIDs();
+      scale(anElementsId, thePoint, theScaleFact,
+            false, theCopyGroups, & mesh_i->GetImpl());
+      mesh_i->CreateGroupServants();
+    }
+    if ( !myPreviewMode ) {
+      pydump << mesh << " = " << this << ".ScaleMakeMesh( "
+             << theObject << ", "
+             << "SMESH.PointStruct( "  << thePoint.x << ", "
+             << thePoint.y << ", " << thePoint.z << " ) ,"
+             << theScaleFact << ", "
+             << theCopyGroups << ", '"
+             << theMeshName << "' )";
+    }
+  }
+
+  //dump "GetGroups"
+  if(!myPreviewMode && mesh_i)
+    mesh_i->GetGroups();
+
+  return mesh._retn();
+}
+
+
+//=======================================================================
+//function : FindCoincidentNodes
+//purpose  :
+//=======================================================================
+
+void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
+                                              SMESH::array_of_long_array_out GroupsOfNodes)
+{
+  initData();
+
+  ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
+  ::SMESH_MeshEditor anEditor( myMesh );
+  set<const SMDS_MeshNode*> nodes; // no input nodes
+  anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
+
+  GroupsOfNodes = new SMESH::array_of_long_array;
   GroupsOfNodes->length( aListOfListOfNodes.size() );
   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ ) {
@@ -3407,8 +3547,9 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr
   SMESHDS_Mesh* aMesh = GetMeshDS();
   set<const SMDS_MeshNode*> nodes;
 
-  if ( !CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
-      SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) {
+  SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
+  if ( !group->_is_nil() && group->GetType() == SMESH::NODE)
+  {
     for(int i = 0; i < aElementsId->length(); i++) {
       CORBA::Long ind = aElementsId[i];
       const SMDS_MeshNode * elem = aMesh->FindNode(ind);
@@ -3427,13 +3568,13 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr
       }
     }
   }
-    
-  
+
+
   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
   ::SMESH_MeshEditor anEditor( myMesh );
   if(!nodes.empty())
     anEditor.FindCoincidentNodes( nodes, Tolerance, aListOfListOfNodes );
-  
+
   GroupsOfNodes = new SMESH::array_of_long_array;
   GroupsOfNodes->length( aListOfListOfNodes.size() );
   ::SMESH_MeshEditor::TListOfListOfNodes::iterator llIt = aListOfListOfNodes.begin();
@@ -3486,6 +3627,8 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
   anEditor.MergeNodes( aListOfListOfNodes );
 
   aTPythonDump <<  "])";
+
+  myMesh->SetIsModified( true );
 }
 
 //=======================================================================
@@ -3493,11 +3636,13 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
 //purpose  :
 //=======================================================================
 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
-                                          SMESH::array_of_long_array_out GroupsOfElementsID)
+                                           SMESH::array_of_long_array_out GroupsOfElementsID)
 {
   initData();
-  if ( !(!CORBA::is_nil(SMESH::SMESH_GroupBase::_narrow(theObject)) &&
-        SMESH::SMESH_GroupBase::_narrow(theObject)->GetType() == SMESH::NODE) ) {
+
+  SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
+  if ( !(!group->_is_nil() && group->GetType() == SMESH::NODE) )
+  {
     typedef list<int> TListOfIDs;
     set<const SMDS_MeshElement*> elems;
     SMESH::long_array_var aElementsId = theObject->GetIDs();
@@ -3507,7 +3652,7 @@ void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObj
       CORBA::Long anID = aElementsId[i];
       const SMDS_MeshElement * elem = aMesh->FindElement(anID);
       if (elem) {
-       elems.insert(elem);
+        elems.insert(elem);
       }
     }
 
@@ -3525,12 +3670,12 @@ void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObj
       aGroup.length( listOfIDs.size() );
       TListOfIDs::iterator idIt = listOfIDs.begin();
       for (int k = 0; idIt != listOfIDs.end(); ++idIt, ++k ) {
-       aGroup[ k ] = *idIt;
+        aGroup[ k ] = *idIt;
       }
     }
 
-  TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
-                <<theObject<<" )";
+    TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
+                  <<theObject<<" )";
   }
 }
 
@@ -3565,6 +3710,8 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO
   ::SMESH_MeshEditor anEditor( myMesh );
   anEditor.MergeElements(aListOfListOfElementsID);
 
+  myMesh->SetIsModified( true );
+
   aTPythonDump << "] )";
 }
 
@@ -3583,6 +3730,86 @@ void SMESH_MeshEditor_i::MergeEqualElements()
   TPythonDump() << this << ".MergeEqualElements()";
 }
 
+//=============================================================================
+/*!
+ * Move the node to a given point
+ */
+//=============================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
+                                            CORBA::Double x,
+                                            CORBA::Double y,
+                                            CORBA::Double z)
+{
+  initData(/*deleteSearchers=*/false);
+
+  const SMDS_MeshNode * node = GetMeshDS()->FindNode( NodeID );
+  if ( !node )
+    return false;
+
+  if ( theNodeSearcher )
+    theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
+
+  if ( myPreviewMode ) // make preview data
+  {
+    // in a preview mesh, make edges linked to a node
+    TPreviewMesh tmpMesh;
+    TIDSortedElemSet linkedNodes;
+    ::SMESH_MeshEditor::GetLinkedNodes( node, linkedNodes );
+    TIDSortedElemSet::iterator nIt = linkedNodes.begin();
+    for ( ; nIt != linkedNodes.end(); ++nIt )
+    {
+      SMDS_MeshEdge edge( node, cast2Node( *nIt ));
+      tmpMesh.Copy( &edge );
+    }
+    // move copied node
+    node = tmpMesh.GetMeshDS()->FindNode( NodeID );
+    if ( node )
+      tmpMesh.GetMeshDS()->MoveNode(node, x, y, z);
+    // fill preview data
+    ::SMESH_MeshEditor anEditor( & tmpMesh );
+    storeResult( anEditor );
+  }
+  else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
+    theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
+  else
+    GetMeshDS()->MoveNode(node, x, y, z);
+
+  if ( !myPreviewMode )
+  {
+    // Update Python script
+    TPythonDump() << "isDone = " << this << ".MoveNode( "
+                  << NodeID << ", " << x << ", " << y << ", " << z << " )";
+
+    myMesh->SetIsModified( true );
+  }
+
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Return ID of node closest to a given point
+ */
+//================================================================================
+
+CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
+                                                  CORBA::Double y,
+                                                  CORBA::Double z)
+{
+  theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
+
+  if ( !theNodeSearcher ) {
+    ::SMESH_MeshEditor anEditor( myMesh );
+    theNodeSearcher = anEditor.GetNodeSearcher();
+  }
+  gp_Pnt p( x,y,z );
+  if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
+    return node->GetID();
+
+  return 0;
+}
+
 //================================================================================
 /*!
  * \brief If the given ID is a valid node ID (nodeID > 0), just move this node, else
@@ -3595,24 +3822,24 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
                                                        CORBA::Double z,
                                                        CORBA::Long   theNodeID)
 {
-  // We keep myNodeSearcher until any mesh modification:
-  // 1) initData() deletes myNodeSearcher at any edition,
-  // 2) TNodeSearcherDeleter - at any mesh compute event and mesh change
+  // We keep theNodeSearcher until any mesh modification:
+  // 1) initData() deletes theNodeSearcher at any edition,
+  // 2) TSearchersDeleter - at any mesh compute event and mesh change
 
-  initData();
+  initData(/*deleteSearchers=*/false);
+
+  theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
 
   int nodeID = theNodeID;
   const SMDS_MeshNode* node = GetMeshDS()->FindNode( nodeID );
-  if ( !node )
+  if ( !node ) // preview moving node
   {
-    static TNodeSearcherDeleter deleter;
-    deleter.Set( myMesh );
-    if ( !myNodeSearcher ) {
+    if ( !theNodeSearcher ) {
       ::SMESH_MeshEditor anEditor( myMesh );
-      myNodeSearcher = anEditor.GetNodeSearcher();
+      theNodeSearcher = anEditor.GetNodeSearcher();
     }
     gp_Pnt p( x,y,z );
-    node = myNodeSearcher->FindClosestTo( p );
+    node = theNodeSearcher->FindClosestTo( p );
   }
   if ( node ) {
     nodeID = node->GetID();
@@ -3636,21 +3863,84 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
       ::SMESH_MeshEditor anEditor( & tmpMesh );
       storeResult( anEditor );
     }
+    else if ( theNodeSearcher ) // move node and update theNodeSearcher data accordingly
+    {
+      theNodeSearcher->MoveNode(node, gp_Pnt( x,y,z ));
+    }
     else
     {
       GetMeshDS()->MoveNode(node, x, y, z);
     }
   }
 
-  if ( !myPreviewMode ) {
+  if ( !myPreviewMode )
+  {
     TPythonDump() << "nodeID = " << this
                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
                   << ", " << nodeID << " )";
+
+    myMesh->SetIsModified( true );
   }
 
   return nodeID;
 }
 
+//=======================================================================
+/*!
+ * Return elements of given type where the given point is IN or ON.
+ *
+ * 'ALL' type means elements of any type excluding nodes
+ */
+//=======================================================================
+
+SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
+                                                           CORBA::Double      y,
+                                                           CORBA::Double      z,
+                                                           SMESH::ElementType type)
+{
+  SMESH::long_array_var res = new SMESH::long_array;
+  vector< const SMDS_MeshElement* > foundElems;
+
+  theSearchersDeleter.Set( myMesh );
+  if ( !theElementSearcher ) {
+    ::SMESH_MeshEditor anEditor( myMesh );
+    theElementSearcher = anEditor.GetElementSearcher();
+  }
+  theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
+                                           SMDSAbs_ElementType( type ),
+                                           foundElems);
+  res->length( foundElems.size() );
+  for ( int i = 0; i < foundElems.size(); ++i )
+    res[i] = foundElems[i]->GetID();
+
+  if ( !myPreviewMode ) // call from tui
+    TPythonDump() << res << " = " << this << ".FindElementsByPoint( "
+                  << x << ", "
+                  << y << ", "
+                  << z << ", "
+                  << type << " )";
+
+  return res._retn();
+}
+
+//=======================================================================
+//function : GetPointState
+//purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
+//           TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
+//=======================================================================
+
+CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
+                                               CORBA::Double y,
+                                               CORBA::Double z)
+{
+  theSearchersDeleter.Set( myMesh );
+  if ( !theElementSearcher ) {
+    ::SMESH_MeshEditor anEditor( myMesh );
+    theElementSearcher = anEditor.GetElementSearcher();
+  }
+  return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
+}
+
 //=======================================================================
 //function : convError
 //purpose  :
@@ -3661,16 +3951,16 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
 static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Sew_Error e )
 {
   switch ( e ) {
-  RETCASE( SEW_OK );
-  RETCASE( SEW_BORDER1_NOT_FOUND );
-  RETCASE( SEW_BORDER2_NOT_FOUND );
-  RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
-  RETCASE( SEW_BAD_SIDE_NODES );
-  RETCASE( SEW_VOLUMES_TO_SPLIT );
-  RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
-  RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
-  RETCASE( SEW_BAD_SIDE1_NODES );
-  RETCASE( SEW_BAD_SIDE2_NODES );
+    RETCASE( SEW_OK );
+    RETCASE( SEW_BORDER1_NOT_FOUND );
+    RETCASE( SEW_BORDER2_NOT_FOUND );
+    RETCASE( SEW_BOTH_BORDERS_NOT_FOUND );
+    RETCASE( SEW_BAD_SIDE_NODES );
+    RETCASE( SEW_VOLUMES_TO_SPLIT );
+    RETCASE( SEW_DIFF_NB_OF_ELEMENTS );
+    RETCASE( SEW_TOPO_DIFF_SETS_OF_ELEMENTS );
+    RETCASE( SEW_BAD_SIDE1_NODES );
+    RETCASE( SEW_BAD_SIDE2_NODES );
   }
   return SMESH::SMESH_MeshEditor::SEW_OK;
 }
@@ -3681,14 +3971,14 @@ static SMESH::SMESH_MeshEditor::Sew_Error convError( const::SMESH_MeshEditor::Se
 //=======================================================================
 
 SMESH::SMESH_MeshEditor::Sew_Error
-  SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
-                                     CORBA::Long SecondNodeID1,
-                                     CORBA::Long LastNodeID1,
-                                     CORBA::Long FirstNodeID2,
-                                     CORBA::Long SecondNodeID2,
-                                     CORBA::Long LastNodeID2,
-                                     CORBA::Boolean CreatePolygons,
-                                     CORBA::Boolean CreatePolyedrs)
+SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
+                                   CORBA::Long SecondNodeID1,
+                                   CORBA::Long LastNodeID1,
+                                   CORBA::Long FirstNodeID2,
+                                   CORBA::Long SecondNodeID2,
+                                   CORBA::Long LastNodeID2,
+                                   CORBA::Boolean CreatePolygons,
+                                   CORBA::Boolean CreatePolyedrs)
 {
   initData();
 
@@ -3734,6 +4024,8 @@ SMESH::SMESH_MeshEditor::Sew_Error
 
   storeResult(anEditor);
 
+  myMesh->SetIsModified( true );
+
   return error;
 }
 
@@ -3789,6 +4081,8 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
 
   storeResult(anEditor);
 
+  myMesh->SetIsModified( true );
+
   return error;
 }
 
@@ -3849,6 +4143,8 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
 
   storeResult(anEditor);
 
+  myMesh->SetIsModified( true );
+
   return error;
 }
 
@@ -3904,15 +4200,17 @@ SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
 
   storeResult(anEditor);
 
+  myMesh->SetIsModified( true );
+
   return error;
 }
 
 //================================================================================
 /*!
  * \brief Set new nodes for given element
 * \param ide - element id
 * \param newIDs - new node ids
 * \retval CORBA::Boolean - true if result is OK
+ * \param ide - element id
+ * \param newIDs - new node ids
+ * \retval CORBA::Boolean - true if result is OK
  */
 //================================================================================
 
@@ -3937,17 +4235,19 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
   }
   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
                 << ide << ", " << newIDs << " )";
-#ifdef _DEBUG_
-  TPythonDump() << "print 'ChangeElemNodes: ', isDone";
-#endif
 
-  return GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
+  bool res = GetMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
+
+  if ( res )
+    myMesh->SetIsModified( true );
+
+  return res;
 }
-  
+
 //================================================================================
 /*!
  * \brief Update myLastCreated* or myPreviewData
 * \param anEditor - it contains last modification results
+ * \param anEditor - it contains last modification results
  */
 //================================================================================
 
@@ -4005,8 +4305,8 @@ void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
       /*if (aMeshElem->GetType() == SMDSAbs_Volume) {
         aType = SMDSAbs_Node;
         isPoly = false;
-      }
-      else*/ {
+        }
+        else*/ {
         aType = aMeshElem->GetType();
         isPoly = aMeshElem->IsPoly();
       }
@@ -4024,7 +4324,7 @@ void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& anEditor)
     myPreviewData->elementConnectivities.length(aNodesConnectivity.size());
     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
       myPreviewData->elementConnectivities[i] = *aConnIter;
-    
+
     return;
   }
 
@@ -4058,7 +4358,7 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
 //================================================================================
 /*!
  * \brief Returns list of it's IDs of created nodes
 * \retval SMESH::long_array* - list of node ID
+ * \retval SMESH::long_array* - list of node ID
  */
 //================================================================================
 
@@ -4070,7 +4370,7 @@ SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
 //================================================================================
 /*!
  * \brief Returns list of it's IDs of created elements
 * \retval SMESH::long_array* - list of elements' ID
+ * \retval SMESH::long_array* - list of elements' ID
  */
 //================================================================================
 
@@ -4089,6 +4389,7 @@ void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
   ::SMESH_MeshEditor anEditor( myMesh );
   anEditor.ConvertToQuadratic(theForce3d);
   TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
+  myMesh->SetIsModified( true );
 }
 
 //=======================================================================
@@ -4101,6 +4402,8 @@ CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
   ::SMESH_MeshEditor anEditor( myMesh );
   CORBA::Boolean isDone = anEditor.ConvertFromQuadratic();
   TPythonDump() << this << ".ConvertFromQuadratic()";
+  if ( isDone )
+    myMesh->SetIsModified( true );
   return isDone;
 }
 
@@ -4164,6 +4467,8 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNode
   bool aResult = aMeshEditor.DoubleNodes( aListOfNodes, aListOfElems );
 
   storeResult( aMeshEditor) ;
+  if ( aResult )
+    myMesh->SetIsModified( true );
 
   return aResult;
 }
@@ -4185,7 +4490,10 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeI
   SMESH::long_array_var aNodes = new SMESH::long_array;
   aNodes->length( 1 );
   aNodes[ 0 ] = theNodeId;
-  return DoubleNodes( aNodes, theModifiedElems );
+  bool done = DoubleNodes( aNodes, theModifiedElems );
+  if ( done )
+    myMesh->SetIsModified( true );
+  return done;
 }
 
 //================================================================================
@@ -4216,7 +4524,12 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(
     aModifiedElems->length( 0 );
   }
 
-  return DoubleNodes( aNodes, aModifiedElems );
+  bool done = DoubleNodes( aNodes, aModifiedElems );
+
+  if ( done )
+    myMesh->SetIsModified( true );
+
+  return done;
 }
 
 //================================================================================
@@ -4267,5 +4580,310 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(
 
   storeResult( aMeshEditor) ;
 
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates 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
+  \sa DoubleNodeGroup(), DoubleNodeGroups()
+*/
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems, 
+                                                   const SMESH::long_array& theNodesNot,
+                                                   const SMESH::long_array& theAffectedElems )
+
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes, anAffected;
+  arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
+  arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
+  arrayToSet(theAffectedElems, aMeshDS, anAffected, SMDSAbs_All);
+
+  bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodes( " << theElems << ", "
+    << theNodesNot << ", " << theAffectedElems << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates 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 theShape - shape to detect affected elements (element which geometric center
+  located on or inside shape).
+  The replicated nodes should be associated to affected elements.
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+  \sa DoubleNodeGroupInRegion(), DoubleNodeGroupsInRegion()
+*/
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion
+( const SMESH::long_array& theElems, 
+  const SMESH::long_array& theNodesNot,
+  GEOM::GEOM_Object_ptr    theShape )
+
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes;
+  arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
+  arrayToSet(theNodesNot, aMeshDS, aNodes, SMDSAbs_Node);
+
+  TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
+  bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodesInRegion( " << theElems << ", "
+    << theNodesNot << ", " << theShape << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates a hole in a mesh by doubling the nodes of some particular elements
+  \param theElems - group of of elements (edges or faces) to be replicated
+  \param theNodesNot - group of nodes not to replicated
+  \param theAffectedElems - group of elements to which the replicated nodes
+  should be associated to.
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+  \sa DoubleNodes(), DoubleNodeGroups()
+*/
+//================================================================================
+
+static void groupToSet(SMESH::SMESH_GroupBase_ptr theGrp,
+                       SMESHDS_Mesh*              theMeshDS,
+                       TIDSortedElemSet&          theElemSet,
+                       const SMDSAbs_ElementType  theType)
+
+{
+  if ( CORBA::is_nil( theGrp ) )
+    return;
+  SMESH::long_array_var anIDs = theGrp->GetIDs();
+  arrayToSet( anIDs, theMeshDS, theElemSet, theType);
+}
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
+                                                       SMESH::SMESH_GroupBase_ptr theNodesNot,
+                                                       SMESH::SMESH_GroupBase_ptr theAffectedElems)
+{
+  if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
+    return false;
+
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes, anAffected;
+  groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
+  groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
+  groupToSet( theAffectedElems, aMeshDS, anAffected, SMDSAbs_All );
+
+  bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodeGroup( " << theElems << ", "
+    << theNodesNot << ", " << theAffectedElems << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates a hole in a mesh by doubling the nodes of some particular elements
+  \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.
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+  \sa DoubleNodesInRegion(), DoubleNodeGroupsInRegion()
+*/
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion( 
+                                                               SMESH::SMESH_GroupBase_ptr theElems,
+                                                               SMESH::SMESH_GroupBase_ptr theNodesNot,
+                                                               GEOM::GEOM_Object_ptr      theShape )
+
+{
+  if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
+    return false;
+
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes, anAffected;
+  groupToSet( theElems, aMeshDS, anElems, SMDSAbs_All ); 
+  groupToSet( theNodesNot, aMeshDS, aNodes, SMDSAbs_Node ); 
+
+  TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
+  bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodeGroupInRegion( " << theElems << ", "
+    << theNodesNot << ", " << theShape << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates 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
+  \param theAffectedElems - group of elements to which the replicated nodes
+  should be associated to.
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+  \sa DoubleNodeGroup(), DoubleNodes()
+*/
+//================================================================================
+
+static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
+                             SMESHDS_Mesh*              theMeshDS,
+                             TIDSortedElemSet&          theElemSet,
+                             const bool                 theIsNodeGrp)
+{
+  for ( int i = 0, n = theGrpList.length(); i < n; i++ )
+  {
+    SMESH::SMESH_GroupBase_var aGrp = theGrpList[ i ];
+    if ( !CORBA::is_nil( aGrp ) && (theIsNodeGrp ? aGrp->GetType() == SMESH::NODE 
+                                    : aGrp->GetType() != SMESH::NODE ) )
+    {
+      SMESH::long_array_var anIDs = aGrp->GetIDs();
+      arrayToSet( anIDs, theMeshDS, theElemSet, theIsNodeGrp ? SMDSAbs_Node : SMDSAbs_All );
+    }
+  }
+}
+
+CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
+                                                        const SMESH::ListOfGroups& theNodesNot,
+                                                        const SMESH::ListOfGroups& theAffectedElems)
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes, anAffected;
+  listOfGroupToSet(theElems, aMeshDS, anElems, false );
+  listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
+  listOfGroupToSet(theAffectedElems, aMeshDS, anAffected, false );
+
+  bool aResult = aMeshEditor.DoubleNodes( anElems, aNodes, anAffected );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
+    << &theNodesNot << ", " << &theAffectedElems << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Creates 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
+  \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.
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+  \sa DoubleNodeGroupInRegion(), DoubleNodesInRegion()
+*/
+//================================================================================
+
+CORBA::Boolean
+SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
+                                                 const SMESH::ListOfGroups& theNodesNot,
+                                                 GEOM::GEOM_Object_ptr      theShape )
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+  TIDSortedElemSet anElems, aNodes;
+  listOfGroupToSet(theElems, aMeshDS, anElems,false );
+  listOfGroupToSet(theNodesNot, aMeshDS, aNodes, true );
+
+  TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
+  bool aResult = aMeshEditor.DoubleNodesInRegion( anElems, aNodes, aShape );
+
+  storeResult( aMeshEditor) ;
+
+  if ( aResult )
+    myMesh->SetIsModified( true );
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".DoubleNodeGroupsInRegion( " << &theElems << ", "
+    << &theNodesNot << ", " << theShape << " )";
+  return aResult;
+}
+
+//================================================================================
+/*!
+  \brief Generated skin mesh (containing 2D cells) from 3D mesh
+   The created 2D mesh elements based on nodes of free faces of boundary volumes
+  \return TRUE if operation has been completed successfully, FALSE otherwise
+*/
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+  bool aResult = aMeshEditor.Make2DMeshFrom3D();
+  storeResult( aMeshEditor) ;
+  
+  TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
   return aResult;
 }