Salome HOME
23024: [CEA 1447] Regression imp_1346_CAS2.py
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index 0709265bf2aab9c7d49509f93d010808abad7b76..d233bb63fa7c62b3ae7ce33c9692b70955526da9 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 //  Author : Nicolas REJNERI
 //  Module : SMESH
 
-#ifdef WNT
+#ifdef WIN32
 #define NOMINMAX
 #endif
 
+// A macro used in SMESH_TryCatch.hxx,
+// it re-raises a CORBA SALOME exception thrown by SMESH_MeshEditor_i and caught by SMESH_CATCH
+#define SMY_OWN_CATCH \
+  catch ( SALOME::SALOME_Exception & e ) { throw e; }
+
 #include "SMESH_MeshEditor_i.hxx"
 
-#include "DriverMED_R_SMESHDS_Mesh.h"
-#include "DriverMED_W_SMESHDS_Mesh.h"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_ElemIterator.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_MeshVolume.hxx"
 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_SetIterator.hxx"
-#include "SMDS_SetIterator.hxx"
 #include "SMDS_VolumeTool.hxx"
-#include "SMESHDS_Command.hxx"
-#include "SMESHDS_CommandType.hxx"
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
 #include "SMESH_ControlsDef.hxx"
 #include "SMESH_Filter_i.hxx"
-#include "SMESH_Filter_i.hxx"
-#include "SMESH_Gen_i.hxx"
 #include "SMESH_Gen_i.hxx"
 #include "SMESH_Group.hxx"
 #include "SMESH_Group_i.hxx"
-#include "SMESH_Group_i.hxx"
-#include "SMESH_MEDMesh_i.hxx"
-#include "SMESH_MeshEditor.hxx"
+#include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MeshPartDS.hxx"
 #include "SMESH_MesherHelper.hxx"
-#include "SMESH_PreMeshInfo.hxx"
-#include "SMESH_PythonDump.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_subMeshEventListener.hxx"
 #include "SMESH_subMesh_i.hxx"
-#include "SMESH_subMesh_i.hxx"
 
-#include "utilities.h"
-#include "Utils_ExceptHandlers.hxx"
-#include "Utils_CorbaException.hxx"
+#include <utilities.h>
+#include <Utils_ExceptHandlers.hxx>
+#include <Utils_CorbaException.hxx>
+#include <SALOMEDS_wrap.hxx>
+#include <SALOME_GenericObj_i.hh>
+#include <Basics_OCCTVersion.hxx>
 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRep_Tool.hxx>
@@ -93,6 +89,8 @@
 #include <sstream>
 #include <limits>
 
+#include "SMESH_TryCatch.hxx" // include after OCCT headers!
+
 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
 
 using namespace std;
@@ -112,7 +110,7 @@ namespace MeshEditor_I {
     SMDSAbs_ElementType myPreviewType; // type to show
     //!< Constructor
     TPreviewMesh(SMDSAbs_ElementType previewElements = SMDSAbs_All) {
-      _isShapeToMesh = (_id =_studyId =_idDoc = 0);
+      _isShapeToMesh = (_id =_studyId = 0);
       _myMeshDS  = new SMESHDS_Mesh( _id, true );
       myPreviewType = previewElements;
     }
@@ -180,6 +178,10 @@ namespace MeshEditor_I {
       return _myMeshDS->AddNodeWithID(anElemNode->X(), anElemNode->Y(), anElemNode->Z(),
                                       anElemNode->GetID());
     }
+    void RemoveAll()
+    {
+      GetMeshDS()->ClearMesh();
+    }
   };// struct TPreviewMesh
 
   static SMESH_NodeSearcher *    theNodeSearcher    = 0;
@@ -226,22 +228,22 @@ namespace MeshEditor_I {
         }
         myMesh = mesh;
         myMeshPartIOR = meshPartIOR;
-        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 );
+        SMESH_subMesh* sm = mesh->GetSubMesh( mesh->GetShapeToMesh() );
+        SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
+        while ( smIt->more() )
+        {
+          sm = smIt->next();
+          sm->SetEventListener( this, 0, sm );
         }
       }
     }
     //!<  delete self from all submeshes
     void Unset(SMESH_Mesh* 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->DeleteEventListener( this );
+      if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining(1) ) {
+        SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator( /*includeSelf=*/true );
+        while ( smIt->more() )
+          smIt->next()->DeleteEventListener( this );
       }
       myMesh = 0;
     }
@@ -276,52 +278,31 @@ namespace MeshEditor_I {
   void arrayToSet(const SMESH::long_array & IDs,
                   const SMESHDS_Mesh*       aMesh,
                   TIDSortedElemSet&         aMap,
-                  const SMDSAbs_ElementType aType = SMDSAbs_All )
+                  const SMDSAbs_ElementType aType = SMDSAbs_All,
+                  SMDS_MeshElement::Filter* aFilter = NULL)
   {
-    for (int i=0; i<IDs.length(); i++) {
-      CORBA::Long ind = IDs[i];
-      const SMDS_MeshElement * elem =
-        (aType == SMDSAbs_Node ? aMesh->FindNode(ind) : aMesh->FindElement(ind));
-      if ( elem && ( aType == SMDSAbs_All || elem->GetType() == aType ))
-        aMap.insert( aMap.end(), elem );
-    }
-  }
-  //================================================================================
-  /*!
-   * \brief Retrieve elements of given type from SMESH_IDSource
-   */
-  //================================================================================
-
-  bool idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
-                     const SMESHDS_Mesh*        theMeshDS,
-                     TIDSortedElemSet&          theElemSet,
-                     const SMDSAbs_ElementType  theType,
-                     const bool                 emptyIfIsMesh=false)
+    SMDS_MeshElement::NonNullFilter filter1;
+    SMDS_MeshElement::TypeFilter    filter2( aType );
 
-  {
-    if ( CORBA::is_nil( theIDSource ) )
-      return false;
-    if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
-      return true;
+    if ( aFilter == NULL )
+      aFilter = ( aType == SMDSAbs_All ) ? (SMDS_MeshElement::Filter*) &filter1 : (SMDS_MeshElement::Filter*) &filter2;
+    
+    SMDS_MeshElement::Filter & filter = *aFilter;
 
-    SMESH::long_array_var anIDs = theIDSource->GetIDs();
-    if ( anIDs->length() == 0 )
-      return false;
-    SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
-    if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
-    {
-      if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
-        arrayToSet( anIDs, theMeshDS, theElemSet, SMDSAbs_Node );
-      else
-        return false;
-    }
+    if ( aType == SMDSAbs_Node )
+      for (int i=0; i<IDs.length(); i++) {
+        const SMDS_MeshElement * elem = aMesh->FindNode( IDs[i] );
+        if ( filter( elem ))
+          aMap.insert( aMap.end(), elem );
+      }
     else
-    {
-      arrayToSet( anIDs, theMeshDS, theElemSet, theType);
-      return bool(anIDs->length()) == bool(theElemSet.size());
-    }
-    return true;
+      for (int i=0; i<IDs.length(); i++) {
+        const SMDS_MeshElement * elem = aMesh->FindElement( IDs[i] );
+        if ( filter( elem ))
+          aMap.insert( aMap.end(), elem );
+      }
   }
+
   //================================================================================
   /*!
    * \brief Retrieve nodes from SMESH_IDSource
@@ -379,7 +360,8 @@ namespace MeshEditor_I {
     if ( !sameElemType )
       elemType = SMDSAbs_All;
 
-    TIDSortedElemSet visitedNodes;
+    vector<bool> isNodeChecked( theMeshDS->NbNodes(), false );
+
     TIDSortedElemSet::const_iterator elemIt = theElements.begin();
     for ( ; elemIt != theElements.end(); ++elemIt )
     {
@@ -388,8 +370,9 @@ namespace MeshEditor_I {
       while ( --i != -1 )
       {
         const SMDS_MeshNode* n = e->GetNode( i );
-        if ( visitedNodes.insert( n ).second )
+        if ( !isNodeChecked[ n->GetID() ])
         {
+          isNodeChecked[ n->GetID() ] = true;
           SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator(elemType);
           while ( invIt->more() )
           {
@@ -447,11 +430,26 @@ SMESH_MeshEditor_i::SMESH_MeshEditor_i(SMESH_Mesh_i* theMesh, bool isPreview):
 
 SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
 {
-  deleteAuxIDSources();
+  PortableServer::POA_var poa = SMESH_Gen_i::GetPOA();
+  PortableServer::ObjectId_var anObjectId = poa->servant_to_id(this);
+  poa->deactivate_object(anObjectId.in());
+
+  //deleteAuxIDSources();
   delete myPreviewMesh;   myPreviewMesh = 0;
   delete myPreviewEditor; myPreviewEditor = 0;
 }
 
+//================================================================================
+/*!
+ * \brief Returns the mesh
+ */
+//================================================================================
+
+SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::GetMesh()
+{
+  return myMesh_i->_this();
+}
+
 //================================================================================
 /*!
  * \brief Clear members
@@ -461,15 +459,32 @@ SMESH_MeshEditor_i::~SMESH_MeshEditor_i()
 void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 {
   if ( myIsPreviewMode ) {
-    if ( myPreviewMesh ) myPreviewMesh->Clear();
+    if ( myPreviewMesh ) myPreviewMesh->RemoveAll();
   }
   else {
     if ( deleteSearchers )
       TSearchersDeleter::Delete();
   }
   getEditor().GetError().reset();
-  getEditor().CrearLastCreated();
+  getEditor().ClearLastCreated();
+}
+
+//================================================================================
+/*!
+ * \brief Increment mesh modif time and optionally record that the performed
+ *        modification may influence futher mesh re-compute.
+ *  \param [in] isReComputeSafe - true if the modification does not infulence
+ *              futher mesh re-compute
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
+{
+  myMesh->GetMeshDS()->Modified();
+  if ( !isReComputeSafe )
+    myMesh->SetIsModified( true );
 }
+
 //================================================================================
 /*!
  * \brief Return either myEditor or myPreviewEditor depending on myIsPreviewMode.
@@ -508,16 +523,6 @@ TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewEle
   return myPreviewMesh;
 }
 
-//================================================================================
-/*!
- * \brief Now does nothing
- */
-//================================================================================
-
-// void SMESH_MeshEditor_i::storeResult(::SMESH_MeshEditor& )
-// {
-// }
-
 //================================================================================
 /*!
  * Return data of mesh edition preview
@@ -525,7 +530,9 @@ TPreviewMesh * SMESH_MeshEditor_i::getPreviewMesh(SMDSAbs_ElementType previewEle
 //================================================================================
 
 SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
-{
+  throw (SALOME::SALOME_Exception)
+{ 
+  SMESH_TRY;
   const bool hasBadElems = ( getEditor().GetError() && getEditor().GetError()->HasBadElems() );
 
   if ( myIsPreviewMode || hasBadElems ) { // --- MeshPreviewStruct filling ---
@@ -543,9 +550,6 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
     else {
       aMeshDS = getEditor().GetMeshDS();
     }
-    int nbEdges = aMeshDS->NbEdges();
-    int nbFaces = aMeshDS->NbFaces();
-    int nbVolum = aMeshDS->NbVolumes();
     myPreviewData = new SMESH::MeshPreviewStruct();
     myPreviewData->nodesXYZ.length(aMeshDS->NbNodes());
 
@@ -555,23 +559,23 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
       if (TPreviewMesh * aPreviewMesh = dynamic_cast< TPreviewMesh* >( getEditor().GetMesh() )) {
         previewType = aPreviewMesh->myPreviewType;
         switch ( previewType ) {
-        case SMDSAbs_Edge  : nbFaces = nbVolum = 0; break;
-        case SMDSAbs_Face  : nbEdges = nbVolum = 0; break;
-        case SMDSAbs_Volume: nbEdges = nbFaces = 0; break;
+        case SMDSAbs_Edge  : break;
+        case SMDSAbs_Face  : break;
+        case SMDSAbs_Volume: break;
         default:;
+          if ( aMeshDS->GetMeshInfo().NbElements() == 0 ) previewType = SMDSAbs_Node;
         }
       }
 
-    myPreviewData->elementTypes.length(nbEdges + nbFaces + nbVolum);
+    myPreviewData->elementTypes.length( aMeshDS->GetMeshInfo().NbElements( previewType ));
     int i = 0, j = 0;
     SMDS_ElemIteratorPtr itMeshElems = aMeshDS->elementsIterator(previewType);
 
     while ( itMeshElems->more() ) {
       const SMDS_MeshElement* aMeshElem = itMeshElems->next();
-      SMDS_ElemIteratorPtr itElemNodes = aMeshElem->nodesIterator();
+      SMDS_NodeIteratorPtr itElemNodes = aMeshElem->nodeIterator();
       while ( itElemNodes->more() ) {
-        const SMDS_MeshNode* aMeshNode =
-          static_cast<const SMDS_MeshNode*>( itElemNodes->next() );
+        const SMDS_MeshNode* aMeshNode = itElemNodes->next();
         int aNodeID = aMeshNode->GetID();
         TNodesMap::iterator anIter = nodesMap.find(aNodeID);
         if ( anIter == nodesMap.end() ) {
@@ -588,12 +592,10 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
       // filling the elements types
       SMDSAbs_ElementType aType = aMeshElem->GetType();
       bool               isPoly = aMeshElem->IsPoly();
-
       myPreviewData->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) aType;
-      myPreviewData->elementTypes[i].isPoly = isPoly;
+      myPreviewData->elementTypes[i].isPoly           = isPoly;
       myPreviewData->elementTypes[i].nbNodesInElement = aMeshElem->NbNodes();
       i++;
-
     }
     myPreviewData->nodesXYZ.length( j );
 
@@ -603,8 +605,10 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
     for( int i = 0; aConnIter != aNodesConnectivity.end(); aConnIter++, i++ )
       myPreviewData->elementConnectivities[i] = *aConnIter;
   }
-
   return myPreviewData._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -615,13 +619,19 @@ SMESH::MeshPreviewStruct* SMESH_MeshEditor_i::GetPreviewData()
 //================================================================================
 
 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::long_array_var myLastCreatedNodes = new SMESH::long_array();
+
   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedNodes();
   myLastCreatedNodes->length( aSeq.Length() );
   for (int i = 1; i <= aSeq.Length(); i++)
     myLastCreatedNodes[i-1] = aSeq.Value(i)->GetID();
+
   return myLastCreatedNodes._retn();
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -632,23 +642,44 @@ SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedNodes()
 //================================================================================
 
 SMESH::long_array* SMESH_MeshEditor_i::GetLastCreatedElems()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::long_array_var myLastCreatedElems = new SMESH::long_array();
+
   const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
   myLastCreatedElems->length( aSeq.Length() );
   for ( int i = 1; i <= aSeq.Length(); i++ )
     myLastCreatedElems[i-1] = aSeq.Value(i)->GetID();
+
   return myLastCreatedElems._retn();
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
+
+//=======================================================================
+//function : ClearLastCreated
+//purpose  : Clears sequences of last created elements and nodes 
+//=======================================================================
+
+void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  getEditor().ClearLastCreated();
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
 /*
  * Returns description of an error/warning occured during the last operation
+ * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
  */
 //=======================================================================
 
 SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::ComputeError_var errOut = new SMESH::ComputeError;
   SMESH_ComputeErrorPtr&  errIn  = getEditor().GetError();
   if ( errIn && !errIn->IsOK() )
@@ -664,21 +695,34 @@ SMESH::ComputeError* SMESH_MeshEditor_i::GetLastError()
     errOut->subShapeID = -1;
     errOut->hasBadMesh = false;
   }
+
   return errOut._retn();
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
 //function : MakeIDSource
-//purpose  : Wrap a sequence of ids in a SMESH_IDSource
+//purpose  : Wrap a sequence of ids in a SMESH_IDSource.
+//           Call UnRegister() as you fininsh using it!!
 //=======================================================================
 
-struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource
+struct SMESH_MeshEditor_i::_IDSource : public virtual POA_SMESH::SMESH_IDSource,
+                                       public virtual SALOME::GenericObj_i
 {
   SMESH::long_array     _ids;
   SMESH::ElementType    _type;
   SMESH::SMESH_Mesh_ptr _mesh;
   SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
   SMESH::long_array* GetMeshInfo() { return 0; }
+  SMESH::long_array* GetNbElementsByType()
+  {
+    SMESH::long_array_var aRes = new SMESH::long_array();
+    aRes->length(SMESH::NB_ELEMENT_TYPES);
+    for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
+      aRes[ i ] = ( i == _type ) ? _ids.length() : 0;
+    return aRes._retn();  
+  }
   SMESH::SMESH_Mesh_ptr GetMesh()  { return SMESH::SMESH_Mesh::_duplicate( _mesh ); }
   bool IsMeshInfoCorrect()         { return true; }
   SMESH::array_of_ElementType* GetTypes()
@@ -690,33 +734,53 @@ struct SMESH_MeshEditor_i::_IDSource : public POA_SMESH::SMESH_IDSource
     }
     return types._retn();
   }
+  SALOMEDS::TMPFile* GetVtkUgStream()
+  {
+    SALOMEDS::TMPFile_var SeqFile;
+    return SeqFile._retn();
+  }
 };
 
 SMESH::SMESH_IDSource_ptr SMESH_MeshEditor_i::MakeIDSource(const SMESH::long_array& ids,
                                                            SMESH::ElementType       type)
 {
-  if ( myAuxIDSources.size() > 10 )
-    deleteAuxIDSources();
-
   _IDSource* idSrc = new _IDSource;
   idSrc->_mesh = myMesh_i->_this();
   idSrc->_ids  = ids;
   idSrc->_type = type;
-  myAuxIDSources.push_back( idSrc );
+  if ( type == SMESH::ALL && ids.length() > 0 )
+    idSrc->_type = myMesh_i->GetElementType( ids[0], true );
 
   SMESH::SMESH_IDSource_var anIDSourceVar = idSrc->_this();
 
   return anIDSourceVar._retn();
 }
 
-void SMESH_MeshEditor_i::deleteAuxIDSources()
+bool SMESH_MeshEditor_i::IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource )
+{
+  return SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource );
+}
+
+CORBA::Long* SMESH_MeshEditor_i::GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource,
+                                                  int&                       nbIds)
 {
-  std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
-  for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
-    delete *idSrcIt;
-  myAuxIDSources.clear();
+  if ( _IDSource* tmpIdSource = SMESH::DownCast<SMESH_MeshEditor_i::_IDSource*>( idSource ))
+  {
+    nbIds = (int) tmpIdSource->_ids.length();
+    return & tmpIdSource->_ids[0];
+  }
+  nbIds = 0;
+  return 0;
 }
 
+// void SMESH_MeshEditor_i::deleteAuxIDSources()
+// {
+//   std::list< _IDSource* >::iterator idSrcIt = myAuxIDSources.begin();
+//   for ( ; idSrcIt != myAuxIDSources.end(); ++idSrcIt )
+//     delete *idSrcIt;
+//   myAuxIDSources.clear();
+// }
+
 //=============================================================================
 /*!
  *
@@ -725,7 +789,9 @@ void SMESH_MeshEditor_i::deleteAuxIDSources()
 
 CORBA::Boolean
 SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   list< int > IdList;
@@ -738,10 +804,12 @@ SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
 
   // Remove Elements
   bool ret = getEditor().Remove( IdList, false );
-  myMesh->GetMeshDS()->Modified();
-  if ( IDsOfElements.length() )
-    myMesh->SetIsModified( true ); // issue 0020693
+
+  declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 ); // issue 0020693
   return ret;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -751,7 +819,9 @@ SMESH_MeshEditor_i::RemoveElements(const SMESH::long_array & IDsOfElements)
 //=============================================================================
 
 CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   list< int > IdList;
@@ -762,10 +832,12 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNo
   TPythonDump() << "isDone = " << this << ".RemoveNodes( " << IDsOfNodes << " )";
 
   bool ret = getEditor().Remove( IdList, true );
-  myMesh->GetMeshDS()->Modified();
-  if ( IDsOfNodes.length() )
-    myMesh->SetIsModified( true ); // issue 0020693
+
+  declareMeshModified( /*isReComputeSafe=*/ !ret ); // issue 0020693
   return ret;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -775,10 +847,11 @@ CORBA::Boolean SMESH_MeshEditor_i::RemoveNodes(const SMESH::long_array & IDsOfNo
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-
   // Update Python script
   TPythonDump() << "nbRemoved = " << this << ".RemoveOrphanNodes()";
 
@@ -794,12 +867,13 @@ CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
 
   int nbNodesBefore = myMesh->NbNodes();
   getEditor().Remove( IdList, true );
-  myMesh->GetMeshDS()->Modified();
-  if ( IdList.size() )
-    myMesh->SetIsModified( true );
   int nbNodesAfter = myMesh->NbNodes();
 
+  declareMeshModified( /*isReComputeSafe=*/ IdList.size() == 0 ); // issue 0020693
   return nbNodesBefore - nbNodesAfter;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -808,9 +882,10 @@ CORBA::Long SMESH_MeshEditor_i::RemoveOrphanNodes()
  */
 //=============================================================================
 
-CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
-                                        CORBA::Double y, CORBA::Double z)
+CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::Double z)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshNode* N = getMeshDS()->AddNode(x, y, z);
@@ -819,9 +894,11 @@ CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
   TPythonDump() << "nodeID = " << this << ".AddNode( "
                 << TVar( x ) << ", " << TVar( y ) << ", " << TVar( z )<< " )";
 
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true ); // issue 0020693
+  declareMeshModified( /*isReComputeSafe=*/false );
   return N->GetID();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -831,7 +908,9 @@ CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
@@ -840,12 +919,11 @@ CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
   // Update Python script
   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
 
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true ); // issue 0020693
+  declareMeshModified( /*isReComputeSafe=*/false );
 
-  if (elem)
-    return elem->GetID();
+  return elem ? elem->GetID() : 0;
 
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -858,6 +936,7 @@ CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
 CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diameter)
   throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   if ( diameter < std::numeric_limits<double>::min() )
@@ -870,12 +949,10 @@ CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diam
   TPythonDump() << "ballElem = "
                 << this << ".AddBall( " << IDOfNode << ", " << diameter <<" )";
 
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true ); // issue 0020693
-
-  if (elem)
-    return elem->GetID();
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
 
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -887,7 +964,9 @@ CORBA::Long SMESH_MeshEditor_i::AddBall(CORBA::Long IDOfNode, CORBA::Double diam
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbNodes = IDsOfNodes.length();
@@ -915,10 +994,10 @@ CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
                   <<n1<<", "<<n2<<", "<<n12<<" ])";
   }
 
-  myMesh->GetMeshDS()->Modified();
-  if(elem)
-    return myMesh->SetIsModified( true ), elem->GetID();
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
 
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -929,7 +1008,9 @@ CORBA::Long SMESH_MeshEditor_i::AddEdge(const SMESH::long_array & IDsOfNodes)
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbNodes = IDsOfNodes.length();
@@ -943,35 +1024,29 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
     nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]);
 
   SMDS_MeshElement* elem = 0;
-  if (NbNodes == 3) {
-    elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]);
-  }
-  else if (NbNodes == 4) {
-    elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]);
-  }
-  else if (NbNodes == 6) {
-    elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
-                                nodes[4], nodes[5]);
-  }
-  else if (NbNodes == 8) {
-    elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
-                                nodes[4], nodes[5], nodes[6], nodes[7]);
-  }
-  else if (NbNodes == 9) {
-    elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
-                                nodes[4], nodes[5], nodes[6], nodes[7], nodes[8] );
-  }
-  else if (NbNodes > 2) {
-    elem = getMeshDS()->AddPolygonalFace(nodes);
+  switch (NbNodes) {
+  case 3: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2]); break;
+  case 4: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3]); break;
+  case 6: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5]); break;
+  case 7: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5], nodes[6]); break;
+  case 8: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5], nodes[6], nodes[7]); break;
+  case 9: elem = getMeshDS()->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5], nodes[6], nodes[7],
+                                      nodes[8] ); break;
+  default: elem = getMeshDS()->AddPolygonalFace(nodes);
   }
 
   // Update Python script
   TPythonDump() << "faceID = " << this << ".AddFace( " << IDsOfNodes << " )";
 
-  myMesh->GetMeshDS()->Modified();
-  if(elem)
-    return myMesh->SetIsModified( true ), elem->GetID();
+  declareMeshModified( /*isReComputeSafe=*/false );
 
+  return elem ? elem->GetID() : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -981,7 +1056,9 @@ CORBA::Long SMESH_MeshEditor_i::AddFace(const SMESH::long_array & IDsOfNodes)
  */
 //=============================================================================
 CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbNodes = IDsOfNodes.length();
@@ -994,8 +1071,11 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO
   // Update Python script
   TPythonDump() <<"faceID = "<<this<<".AddPolygonalFace( "<<IDsOfNodes<<" )";
 
-  myMesh->GetMeshDS()->Modified();
-  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1006,7 +1086,9 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbNodes = IDsOfNodes.length();
@@ -1047,10 +1129,10 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddVolume( " << IDsOfNodes << " )";
 
-  myMesh->GetMeshDS()->Modified();
-  if(elem)
-    return myMesh->SetIsModified( true ), elem->GetID();
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
 
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -1061,7 +1143,9 @@ CORBA::Long SMESH_MeshEditor_i::AddVolume(const SMESH::long_array & IDsOfNodes)
 //=============================================================================
 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & IDsOfNodes,
                                                      const SMESH::long_array & Quantities)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbNodes = IDsOfNodes.length();
@@ -1083,9 +1167,12 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & I
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddPolyhedralVolume( "
                 << IDsOfNodes << ", " << Quantities << " )";
-  myMesh->GetMeshDS()->Modified();
 
-  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1095,7 +1182,9 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolume (const SMESH::long_array & I
 //=============================================================================
 
 CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_array & IdsOfFaces)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   int NbFaces = IdsOfFaces.length();
@@ -1117,9 +1206,12 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_ar
   // Update Python script
   TPythonDump() << "volID = " << this << ".AddPolyhedralVolumeByFaces( "
                 << IdsOfFaces << " )";
-  myMesh->GetMeshDS()->Modified();
 
-  return elem ? ( myMesh->SetIsModified( true ), elem->GetID()) : 0;
+  declareMeshModified( /*isReComputeSafe=*/false );
+  return elem ? elem->GetID() : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1139,6 +1231,7 @@ SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObje
                                                const char*               theGroupName)
   throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESH::SMESH_IDSource_var result;
@@ -1191,6 +1284,9 @@ SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObje
          << theObject << ", '" << theGroupName << "' )";
 
   return result._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1205,7 +1301,7 @@ SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObje
 void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexID)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
+  SMESH_TRY;
 
   SMESHDS_Mesh * mesh = getMeshDS();
   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
@@ -1222,6 +1318,8 @@ void SMESH_MeshEditor_i::SetNodeOnVertex(CORBA::Long NodeID, CORBA::Long VertexI
   mesh->SetNodeOnVertex( node, VertexID );
 
   myMesh->SetIsModified( true );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -1238,7 +1336,7 @@ void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
                                        CORBA::Double paramOnEdge)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
+  SMESH_TRY;
 
   SMESHDS_Mesh * mesh = getMeshDS();
   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
@@ -1260,6 +1358,8 @@ void SMESH_MeshEditor_i::SetNodeOnEdge(CORBA::Long NodeID, CORBA::Long EdgeID,
   mesh->SetNodeOnEdge( node, EdgeID, paramOnEdge );
 
   myMesh->SetIsModified( true );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -1277,8 +1377,7 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
                                        CORBA::Double u, CORBA::Double v)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   SMESHDS_Mesh * mesh = getMeshDS();
   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
   if ( !node )
@@ -1310,6 +1409,8 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
 
   mesh->SetNodeOnFace( node, FaceID, u, v );
   myMesh->SetIsModified( true );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -1324,8 +1425,7 @@ void SMESH_MeshEditor_i::SetNodeOnFace(CORBA::Long NodeID, CORBA::Long FaceID,
 void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   SMESHDS_Mesh * mesh = getMeshDS();
   SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( mesh->FindNode(NodeID) );
   if ( !node )
@@ -1341,7 +1441,7 @@ void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID
 
   mesh->SetNodeInVolume( node, SolidID );
 
-  // myMesh->SetIsModified( true ); - SetNodeInVolume() can't prevent re-compute, I believe
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -1349,7 +1449,6 @@ void SMESH_MeshEditor_i::SetNodeInVolume(CORBA::Long NodeID, CORBA::Long SolidID
  * \brief Bind an element to a shape
  * \param ElementID - element ID
  * \param ShapeID - shape ID available through GEOM_Object.GetSubShapeIndices()[0]
- * \retval boolean - false if ElementID or ShapeID is invalid
  */
 //=============================================================================
 
@@ -1357,14 +1456,13 @@ void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
                                                CORBA::Long ShapeID)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   SMESHDS_Mesh * mesh = getMeshDS();
   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(mesh->FindElement(ElementID));
   if ( !elem )
     THROW_SALOME_CORBA_EXCEPTION("Invalid ElementID", SALOME::BAD_PARAM);
 
-  if ( mesh->MaxShapeIndex() < ShapeID )
+  if ( mesh->MaxShapeIndex() < ShapeID || ShapeID < 1 )
     THROW_SALOME_CORBA_EXCEPTION("Invalid ShapeID", SALOME::BAD_PARAM);
 
   TopoDS_Shape shape = mesh->IndexToShape( ShapeID );
@@ -1377,6 +1475,8 @@ void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
   mesh->SetMeshElementOnShape( elem, ShapeID );
 
   myMesh->SetIsModified( true );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -1387,7 +1487,9 @@ void SMESH_MeshEditor_i::SetMeshElementOnShape(CORBA::Long ElementID,
 
 CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
                                                CORBA::Long NodeID2)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
@@ -1399,11 +1501,13 @@ CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
   TPythonDump() << "isDone = " << this << ".InverseDiag( "
                 << NodeID1 << ", " << NodeID2 << " )";
 
-
   int ret =  getEditor().InverseDiag ( n1, n2 );
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+
+  declareMeshModified( /*isReComputeSafe=*/false );
   return ret;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1414,7 +1518,9 @@ CORBA::Boolean SMESH_MeshEditor_i::InverseDiag(CORBA::Long NodeID1,
 
 CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
                                               CORBA::Long NodeID2)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshNode * n1 = getMeshDS()->FindNode( NodeID1 );
@@ -1429,12 +1535,12 @@ CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
 
   bool stat = getEditor().DeleteDiag ( n1, n2 );
 
-  myMesh->GetMeshDS()->Modified();
-  if ( stat )
-    myMesh->SetIsModified( true ); // issue 0020693
-
+  declareMeshModified( /*isReComputeSafe=*/!stat );
 
   return stat;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
@@ -1444,7 +1550,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DeleteDiag(CORBA::Long NodeID1,
 //=============================================================================
 
 CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfElements)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   for (int i = 0; i < IDsOfElements.length(); i++)
@@ -1457,13 +1565,12 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfEleme
   // Update Python script
   TPythonDump() << "isDone = " << this << ".Reorient( " << IDsOfElements << " )";
 
-  myMesh->GetMeshDS()->Modified();
-  if ( IDsOfElements.length() )
-    myMesh->SetIsModified( true ); // issue 0020693
-
+  declareMeshModified( /*isReComputeSafe=*/ IDsOfElements.length() == 0 );
   return true;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
@@ -1472,18 +1579,26 @@ CORBA::Boolean SMESH_MeshEditor_i::Reorient(const SMESH::long_array & IDsOfEleme
 //=============================================================================
 
 CORBA::Boolean SMESH_MeshEditor_i::ReorientObject(SMESH::SMESH_IDSource_ptr theObject)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump; // suppress dump in Reorient()
 
+  prepareIdSource( theObject );
+
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = Reorient(anElementsId);
 
   // Update Python script
   aTPythonDump << "isDone = " << this << ".ReorientObject( " << theObject << " )";
 
+  declareMeshModified( /*isReComputeSafe=*/ anElementsId->length() == 0 );
   return isDone;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -1503,12 +1618,15 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
                                            const SMESH::PointStruct& thePoint)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   initData(/*deleteSearchers=*/false);
 
   TIDSortedElemSet elements;
-  if ( !idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1))
+  IDSource_Error error;
+  idSourceToSet( the2Dgroup, getMeshDS(), elements, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
+  if ( error == IDSource_EMPTY )
+    return 0;
+  if ( error == IDSource_INVALID )
     THROW_SALOME_CORBA_EXCEPTION("No faces in given group", SALOME::BAD_PARAM);
 
 
@@ -1532,14 +1650,14 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
         if ( myMesh->NbFaces() == 0 )
           THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM);
 
-        theElementSearcher = myEditor.GetElementSearcher();
+        theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
       }
       else
       {
         typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
         SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
 
-        theElementSearcher = myEditor.GetElementSearcher(elemsIt);
+        theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt);
       }
     }
     // find a face
@@ -1560,8 +1678,7 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
   int nbReori = getEditor().Reorient2D( elements, dirVec, face );
 
   if ( nbReori ) {
-    myMesh->SetIsModified( true );
-    myMesh->GetMeshDS()->Modified();
+    declareMeshModified( /*isReComputeSafe=*/false );
   }
   TPythonDump() << this << ".Reorient2D( "
                 << the2Dgroup << ", "
@@ -1570,22 +1687,86 @@ CORBA::Long SMESH_MeshEditor_i::Reorient2D(SMESH::SMESH_IDSource_ptr the2Dgroup,
                 << thePoint << " )";
 
   return nbReori;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
+
+//=======================================================================
+//function : Reorient2DBy3D
+//purpose  : Reorient faces basing on orientation of adjacent volumes.
+//=======================================================================
+
+CORBA::Long SMESH_MeshEditor_i::Reorient2DBy3D(const SMESH::ListOfIDSources& faceGroups,
+                                               SMESH::SMESH_IDSource_ptr     volumeGroup,
+                                               CORBA::Boolean                outsideNormal)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  TIDSortedElemSet volumes;
+  IDSource_Error volsError;
+  idSourceToSet( volumeGroup, getMeshDS(), volumes, SMDSAbs_Volume, /*emptyIfMesh=*/1, &volsError);
+
+  int nbReori = 0;
+  for ( size_t i = 0; i < faceGroups.length(); ++i )
+  {
+    SMESH::SMESH_IDSource_ptr faceGrp = faceGroups[i].in();
+
+    TIDSortedElemSet faces;
+    IDSource_Error error;
+    idSourceToSet( faceGrp, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/1, &error );
+    if ( error == IDSource_INVALID && faceGroups.length() == 1 )
+      THROW_SALOME_CORBA_EXCEPTION("No faces in a given object", SALOME::BAD_PARAM);
+    if ( error == IDSource_OK && volsError != IDSource_OK )
+      THROW_SALOME_CORBA_EXCEPTION("No volumes in a given object", SALOME::BAD_PARAM);
+
+    nbReori += getEditor().Reorient2DBy3D( faces, volumes, outsideNormal );
+
+    if ( error != IDSource_EMPTY && faces.empty() ) // all faces in the mesh treated
+      break;
+  }
+
+  if ( nbReori ) {
+    declareMeshModified( /*isReComputeSafe=*/false );
+  }
+  TPythonDump() << this << ".Reorient2DBy3D( "
+                << faceGroups << ", "
+                << volumeGroup << ", "
+                << outsideNormal << " )";
+
+  return nbReori;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=============================================================================
 /*!
- *
+ * \brief Fuse neighbour triangles into quadrangles.
  */
 //=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfElements,
                                               SMESH::NumericalFunctor_ptr Criterion,
                                               CORBA::Double               MaxAngle)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
-  TIDSortedElemSet faces;
-  arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face);
+  TIDSortedElemSet faces,copyFaces;
+  SMDS_MeshElement::GeomFilter triaFilter(SMDSGeom_TRIANGLE);
+  arrayToSet(IDsOfElements, aMesh, faces, SMDSAbs_Face, & triaFilter);
+  TIDSortedElemSet* workElements = & faces;
+
+  if ( myIsPreviewMode ) {
+    SMDSAbs_ElementType select =  SMDSAbs_Face;
+    getPreviewMesh( SMDSAbs_Face )->Copy( faces, copyFaces, select );
+    workElements = & copyFaces;
+  }
 
   SMESH::NumericalFunctor_i* aNumericalFunctor =
     dynamic_cast<SMESH::NumericalFunctor_i*>( SMESH_Gen_i::GetServant( Criterion ).in() );
@@ -1595,55 +1776,67 @@ CORBA::Boolean SMESH_MeshEditor_i::TriToQuad (const SMESH::long_array &   IDsOfE
   else
     aCrit = aNumericalFunctor->GetNumericalFunctor();
 
-  // Update Python script
-  TPythonDump() << "isDone = " << this << ".TriToQuad( "
-                << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
-
-
-  bool stat = getEditor().TriToQuad( faces, aCrit, MaxAngle );
-  myMesh->GetMeshDS()->Modified();
-  if ( stat )
-    myMesh->SetIsModified( true ); // issue 0020693
+  if ( !myIsPreviewMode ) {
+    // Update Python script
+    TPythonDump() << "isDone = " << this << ".TriToQuad( "
+                  << IDsOfElements << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
+  }
 
+  bool stat = getEditor().TriToQuad( *workElements, aCrit, MaxAngle );
 
+  declareMeshModified( /*isReComputeSafe=*/!stat );
   return stat;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
- *
+ * \brief Fuse neighbour triangles into quadrangles.
  */
 //=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::TriToQuadObject (SMESH::SMESH_IDSource_ptr   theObject,
                                                     SMESH::NumericalFunctor_ptr Criterion,
                                                     CORBA::Double               MaxAngle)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump;  // suppress dump in TriToQuad()
+
+  prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = TriToQuad(anElementsId, Criterion, MaxAngle);
 
-  SMESH::NumericalFunctor_i* aNumericalFunctor =
-    SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
+  if ( !myIsPreviewMode ) {
+    SMESH::NumericalFunctor_i* aNumericalFunctor =
+      SMESH::DownCast<SMESH::NumericalFunctor_i*>( Criterion );
 
-  // Update Python script
-  aTPythonDump << "isDone = " << this << ".TriToQuadObject("
-               << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
+    // Update Python script
+    aTPythonDump << "isDone = " << this << ".TriToQuadObject("
+                 << theObject << ", " << aNumericalFunctor << ", " << TVar( MaxAngle ) << " )";
+  }
 
   return isDone;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
- *
+ * \brief Split quadrangles into triangles.
  */
 //=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfElements,
                                               SMESH::NumericalFunctor_ptr Criterion)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -1663,27 +1856,30 @@ CORBA::Boolean SMESH_MeshEditor_i::QuadToTri (const SMESH::long_array &   IDsOfE
   TPythonDump() << "isDone = " << this << ".QuadToTri( " << IDsOfElements << ", " << aNumericalFunctor << " )";
 
   CORBA::Boolean stat = getEditor().QuadToTri( faces, aCrit );
-  myMesh->GetMeshDS()->Modified();
-  if ( stat )
-    myMesh->SetIsModified( true ); // issue 0020693
-
 
+  declareMeshModified( /*isReComputeSafe=*/false );
   return stat;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
- *
+ * \brief Split quadrangles into triangles.
  */
 //=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr   theObject,
                                                     SMESH::NumericalFunctor_ptr Criterion)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump;  // suppress dump in QuadToTri()
 
+  prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = QuadToTri(anElementsId, Criterion);
 
@@ -1693,18 +1889,48 @@ CORBA::Boolean SMESH_MeshEditor_i::QuadToTriObject (SMESH::SMESH_IDSource_ptr
   // Update Python script
   aTPythonDump << "isDone = " << this << ".QuadToTriObject( " << theObject << ", " << aNumericalFunctor << " )";
 
+  declareMeshModified( /*isReComputeSafe=*/false );
   return isDone;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
-//=============================================================================
+//================================================================================
 /*!
- *
+ * \brief Split each of quadrangles into 4 triangles.
+ *  \param [in] theObject - theQuads Container of quadrangles to split.
  */
-//=============================================================================
+//================================================================================
+
+void SMESH_MeshEditor_i::QuadTo4Tri (SMESH::SMESH_IDSource_ptr theObject)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+
+  TIDSortedElemSet faces;
+  if ( !idSourceToSet( theObject, getMeshDS(), faces, SMDSAbs_Face, /*emptyIfIsMesh=*/true ) &&
+       faces.empty() )
+    THROW_SALOME_CORBA_EXCEPTION("No faces given", SALOME::BAD_PARAM);
+
+  getEditor().QuadTo4Tri( faces );
+  TPythonDump() << this << ".QuadTo4Tri( " << theObject << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
+//=============================================================================
+/*!
+ * \brief Split quadrangles into triangles.
+ */
+//=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfElements,
                                               CORBA::Boolean            Diag13)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -1716,28 +1942,30 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuad (const SMESH::long_array & IDsOfEle
                 << IDsOfElements << ", " << Diag13 << " )";
 
   CORBA::Boolean stat = getEditor().QuadToTri( faces, Diag13 );
-  myMesh->GetMeshDS()->Modified();
-  if ( stat )
-    myMesh->SetIsModified( true ); // issue 0020693
-
-
 
+  declareMeshModified( /*isReComputeSafe=*/ !stat );
   return stat;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
- *
+ * \brief Split quadrangles into triangles.
  */
 //=============================================================================
+
 CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr theObject,
                                                     CORBA::Boolean            Diag13)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump;  // suppress dump in SplitQuad()
 
+  prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = SplitQuad(anElementsId, Diag13);
 
@@ -1745,18 +1973,29 @@ CORBA::Boolean SMESH_MeshEditor_i::SplitQuadObject (SMESH::SMESH_IDSource_ptr th
   aTPythonDump << "isDone = " << this << ".SplitQuadObject( "
                << theObject << ", " << Diag13 << " )";
 
+  declareMeshModified( /*isReComputeSafe=*/!isDone );
   return isDone;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 
 //=============================================================================
 /*!
- *  BestSplit
+ * Find better splitting of the given quadrangle.
+ *  \param IDOfQuad  ID of the quadrangle to be splitted.
+ *  \param Criterion A criterion to choose a diagonal for splitting.
+ *  \return 1 if 1-3 diagonal is better, 2 if 2-4
+ *          diagonal is better, 0 if error occurs.
  */
 //=============================================================================
+
 CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
                                            SMESH::NumericalFunctor_ptr Criterion)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshElement* quad = getMeshDS()->FindElement(IDOfQuad);
@@ -1770,9 +2009,13 @@ CORBA::Long SMESH_MeshEditor_i::BestSplit (CORBA::Long                 IDOfQuad,
     else
       aCrit.reset(new SMESH::Controls::AspectRatio());
 
-    return getEditor().BestSplit(quad, aCrit);
+    int id = getEditor().BestSplit(quad, aCrit);
+    declareMeshModified( /*isReComputeSafe=*/ id < 1 );
+    return id;
   }
-  return -1;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -1785,23 +2028,86 @@ void SMESH_MeshEditor_i::SplitVolumesIntoTetra (SMESH::SMESH_IDSource_ptr elems,
                                                 CORBA::Short              methodFlags)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   initData();
 
-  SMESH::long_array_var anElementsId = elems->GetIDs();
+  ::SMESH_MeshEditor::TFacetOfElem elemSet;
+  const int noneFacet = -1;
+  SMDS_ElemIteratorPtr volIt = myMesh_i->GetElements( elems, SMESH::VOLUME );
+  while( volIt->more() )
+    elemSet.insert( elemSet.end(), make_pair( volIt->next(), noneFacet ));
+
+  getEditor().SplitVolumes( elemSet, int( methodFlags ));
+  declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
+
+  TPythonDump() << this << ".SplitVolumesIntoTetra( "
+                << elems << ", " << methodFlags << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
+
+//================================================================================
+/*!
+ * \brief Split hexahedra into triangular prisms
+ *  \param elems - elements to split
+ *  \param facetToSplitNormal - normal used to find a facet of hexahedron
+ *         to split into triangles
+ *  \param methodFlags - flags passing splitting method:
+ *         1 - split the hexahedron into 2 prisms
+ *         2 - split the hexahedron into 4 prisms
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::SplitHexahedraIntoPrisms (SMESH::SMESH_IDSource_ptr  elems,
+                                                   const SMESH::PointStruct & startHexPoint,
+                                                   const SMESH::DirStruct&    facetToSplitNormal,
+                                                   CORBA::Short               methodFlags,
+                                                   CORBA::Boolean             allDomains)
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_TRY;
+  initData();
+  prepareIdSource( elems );
+
+  gp_Ax1 facetNorm( gp_Pnt( startHexPoint.x,
+                            startHexPoint.y,
+                            startHexPoint.z ),
+                    gp_Dir( facetToSplitNormal.PS.x,
+                            facetToSplitNormal.PS.y,
+                            facetToSplitNormal.PS.z ));
   TIDSortedElemSet elemSet;
-  arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume );
+  SMESH::long_array_var anElementsId = elems->GetIDs();
+  SMDS_MeshElement::GeomFilter filter( SMDSGeom_HEXA );
+  arrayToSet( anElementsId, getMeshDS(), elemSet, SMDSAbs_Volume, &filter );
 
-  getEditor().SplitVolumesIntoTetra( elemSet, int( methodFlags ));
-  myMesh->GetMeshDS()->Modified();
+  ::SMESH_MeshEditor::TFacetOfElem elemFacets;
+  while ( !elemSet.empty() )
+  {
+    getEditor().GetHexaFacetsToSplit( elemSet, facetNorm, elemFacets );
+    if ( !allDomains )
+      break;
 
+    ::SMESH_MeshEditor::TFacetOfElem::iterator ef = elemFacets.begin();
+    for ( ; ef != elemFacets.end(); ++ef )
+      elemSet.erase( ef->first );
+  }
 
-//   if ( myLastCreatedElems.length() ) - it does not influence Compute()
-//     myMesh->SetIsModified( true ); // issue 0020693
+  if ( methodFlags == 2 )
+    methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_4_PRISMS );
+  else
+    methodFlags = int( ::SMESH_MeshEditor::HEXA_TO_2_PRISMS );
 
-  TPythonDump() << this << ".SplitVolumesIntoTetra( "
-                << elems << ", " << methodFlags << " )";
+  getEditor().SplitVolumes( elemFacets, int( methodFlags ));
+  declareMeshModified( /*isReComputeSafe=*/true ); // it does not influence Compute()
+
+  TPythonDump() << this << ".SplitHexahedraIntoPrisms( "
+                << elems << ", "
+                << startHexPoint << ", "
+                << facetToSplitNormal<< ", "
+                << methodFlags<< ", "
+                << allDomains << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -1815,6 +2121,7 @@ SMESH_MeshEditor_i::Smooth(const SMESH::long_array &              IDsOfElements,
                            CORBA::Long                            MaxNbOfIterations,
                            CORBA::Double                          MaxAspectRatio,
                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
+  throw (SALOME::SALOME_Exception)
 {
   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
                  MaxAspectRatio, Method, false );
@@ -1832,6 +2139,7 @@ SMESH_MeshEditor_i::SmoothParametric(const SMESH::long_array &              IDsO
                                      CORBA::Long                            MaxNbOfIterations,
                                      CORBA::Double                          MaxAspectRatio,
                                      SMESH::SMESH_MeshEditor::Smooth_Method Method)
+  throw (SALOME::SALOME_Exception)
 {
   return smooth( IDsOfElements, IDsOfFixedNodes, MaxNbOfIterations,
                  MaxAspectRatio, Method, true );
@@ -1849,6 +2157,7 @@ SMESH_MeshEditor_i::SmoothObject(SMESH::SMESH_IDSource_ptr              theObjec
                                  CORBA::Long                            MaxNbOfIterations,
                                  CORBA::Double                          MaxAspectRatio,
                                  SMESH::SMESH_MeshEditor::Smooth_Method Method)
+  throw (SALOME::SALOME_Exception)
 {
   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
                        MaxAspectRatio, Method, false);
@@ -1866,6 +2175,7 @@ SMESH_MeshEditor_i::SmoothParametricObject(SMESH::SMESH_IDSource_ptr
                                            CORBA::Long                            MaxNbOfIterations,
                                            CORBA::Double                          MaxAspectRatio,
                                            SMESH::SMESH_MeshEditor::Smooth_Method Method)
+  throw (SALOME::SALOME_Exception)
 {
   return smoothObject (theObject, IDsOfFixedNodes, MaxNbOfIterations,
                        MaxAspectRatio, Method, true);
@@ -1885,7 +2195,9 @@ SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
                            CORBA::Double                          MaxAspectRatio,
                            SMESH::SMESH_MeshEditor::Smooth_Method Method,
                            bool                                   IsParametric)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -1907,9 +2219,7 @@ SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
   getEditor().Smooth(elements, fixedNodes, method,
                   MaxNbOfIterations, MaxAspectRatio, IsParametric );
 
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true ); // issue 0020693
-
+  declareMeshModified( /*isReComputeSafe=*/true ); // does not prevent re-compute
 
   // Update Python script
   TPythonDump() << "isDone = " << this << "."
@@ -1921,8 +2231,10 @@ SMESH_MeshEditor_i::smooth(const SMESH::long_array &              IDsOfElements,
                      "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
 
   return true;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
@@ -1937,11 +2249,14 @@ SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObjec
                                  CORBA::Double                          MaxAspectRatio,
                                  SMESH::SMESH_MeshEditor::Smooth_Method Method,
                                  bool                                   IsParametric)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump;  // suppress dump in smooth()
 
+  prepareIdSource( theObject );
   SMESH::long_array_var anElementsId = theObject->GetIDs();
   CORBA::Boolean isDone = smooth (anElementsId, IDsOfFixedNodes, MaxNbOfIterations,
                                   MaxAspectRatio, Method, IsParametric);
@@ -1956,8 +2271,10 @@ SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObjec
                     "CENTROIDAL_SMOOTH )" : "LAPLACIAN_SMOOTH )");
 
   return isDone;
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=============================================================================
 /*!
@@ -1966,13 +2283,16 @@ SMESH_MeshEditor_i::smoothObject(SMESH::SMESH_IDSource_ptr              theObjec
 //=============================================================================
 
 void SMESH_MeshEditor_i::RenumberNodes()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   // Update Python script
   TPythonDump() << this << ".RenumberNodes()";
 
   getMeshDS()->Renumber( true );
-}
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
 
 //=============================================================================
 /*!
@@ -1981,11 +2301,15 @@ void SMESH_MeshEditor_i::RenumberNodes()
 //=============================================================================
 
 void SMESH_MeshEditor_i::RenumberElements()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   // Update Python script
   TPythonDump() << this << ".RenumberElements()";
 
   getMeshDS()->Renumber( false );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -1995,750 +2319,468 @@ void SMESH_MeshEditor_i::RenumberElements()
 //=======================================================================
 
 SMESH::ListOfGroups* SMESH_MeshEditor_i::getGroups(const std::list<int>* groupIDs)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   if ( !groupIDs )
     return 0;
   myMesh_i->CreateGroupServants();
   return myMesh_i->GetGroups( *groupIDs );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
-//function : rotationSweep
+//function : RotationSweepObjects
 //purpose  :
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::rotationSweep(const SMESH::long_array & theIDsOfElements,
-                                  const SMESH::AxisStruct & theAxis,
-                                  CORBA::Double             theAngleInRadians,
-                                  CORBA::Long               theNbOfSteps,
-                                  CORBA::Double             theTolerance,
-                                  const bool                theMakeGroups,
-                                  const SMDSAbs_ElementType theElementType)
+SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes,
+                                         const SMESH::ListOfIDSources & theEdges,
+                                         const SMESH::ListOfIDSources & theFaces,
+                                         const SMESH::AxisStruct &      theAxis,
+                                         CORBA::Double                  theAngleInRadians,
+                                         CORBA::Long                    theNbOfSteps,
+                                         CORBA::Double                  theTolerance,
+                                         const bool                     theMakeGroups)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-  TIDSortedElemSet inElements, copyElements;
-  arrayToSet(theIDsOfElements, getMeshDS(), inElements, theElementType);
+  TIDSortedElemSet elemsNodes[2];
+  for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
+    SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
+    while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
+  }
+  for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
+    idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
+  for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
+    idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
 
-  TIDSortedElemSet* workElements = & inElements;
+  TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
   bool              makeWalls=true;
   if ( myIsPreviewMode )
   {
     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
-    getPreviewMesh( SMDSAbs_Face )->Copy( inElements, copyElements, select, avoid );
-    workElements = & copyElements;
-    //makeWalls = false;
+    TPreviewMesh * tmpMesh = getPreviewMesh();
+    tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
+    tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
+    workElements = & copyElements[0];
+    //makeWalls = false; -- faces are needed for preview
   }
 
+  TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
+
   gp_Ax1 Ax1 (gp_Pnt( theAxis.x,  theAxis.y,  theAxis.z ),
               gp_Vec( theAxis.vx, theAxis.vy, theAxis.vz ));
 
   ::SMESH_MeshEditor::PGroupIDs groupIds =
-      getEditor().RotationSweep (*workElements, Ax1, theAngleInRadians,
+      getEditor().RotationSweep (workElements, Ax1, theAngleInRadians,
                                  theNbOfSteps, theTolerance, theMakeGroups, makeWalls);
-  myMesh->GetMeshDS()->Modified();
 
-  //  myMesh->SetIsModified( true ); -- it does not influence Compute()
+  SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
 
-  return theMakeGroups ? getGroups(groupIds.get()) : 0;
-}
+  declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
 
-//=======================================================================
-//function : RotationSweep
-//purpose  :
-//=======================================================================
+  if ( !myIsPreviewMode )
+  {
+    dumpGroupsList( aPythonDump, aGroups );
+    aPythonDump << this<< ".RotationSweepObjects( "
+                << theNodes                  << ", "
+                << theEdges                  << ", "
+                << theFaces                  << ", "
+                << theAxis                   << ", "
+                << TVar( theAngleInRadians ) << ", "
+                << TVar( theNbOfSteps      ) << ", "
+                << TVar( theTolerance      ) << ", "
+                << theMakeGroups             << " )";
+  }
+
+  return aGroups ? aGroups : new SMESH::ListOfGroups;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
-void SMESH_MeshEditor_i::RotationSweep(const SMESH::long_array & theIDsOfElements,
-                                       const SMESH::AxisStruct & theAxis,
-                                       CORBA::Double             theAngleInRadians,
-                                       CORBA::Long               theNbOfSteps,
-                                       CORBA::Double             theTolerance)
+namespace MeshEditor_I
 {
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".RotationSweep( "
-                  << theIDsOfElements          << ", "
-                  << theAxis                   << ", "
-                  << TVar( theAngleInRadians ) << ", "
-                  << TVar( theNbOfSteps      ) << ", "
-                  << TVar( theTolerance      ) << " )";
-  }
-  rotationSweep(theIDsOfElements,
-                theAxis,
-                theAngleInRadians,
-                theNbOfSteps,
-                theTolerance,
-                false);
+  /*!
+   * \brief Structure used to pass extrusion parameters to ::SMESH_MeshEditor
+   */
+  struct ExtrusionParams : public ::SMESH_MeshEditor::ExtrusParam
+  {
+    bool myIsExtrusionByNormal;
+
+    static int makeFlags( CORBA::Boolean MakeGroups,
+                          CORBA::Boolean ByAverageNormal = false,
+                          CORBA::Boolean UseInputElemsOnly = false,
+                          CORBA::Long    Flags = 0,
+                          CORBA::Boolean MakeBoundary = true )
+    {
+      if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
+      if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
+      if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
+      if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
+      return Flags;
+    }
+    // standard params
+    ExtrusionParams(const SMESH::DirStruct &  theDir,
+                    CORBA::Long               theNbOfSteps,
+                    CORBA::Boolean            theMakeGroups):
+      ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
+                                                theDir.PS.y,
+                                                theDir.PS.z ),
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups )),
+      myIsExtrusionByNormal( false )
+    {
+    }
+    // advanced params
+    ExtrusionParams(const SMESH::DirStruct &  theDir,
+                    CORBA::Long               theNbOfSteps,
+                    CORBA::Boolean            theMakeGroups,
+                    CORBA::Long               theExtrFlags,
+                    CORBA::Double             theSewTolerance):
+      ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
+                                                theDir.PS.y,
+                                                theDir.PS.z ),
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups, false, false,
+                                                   theExtrFlags, false ),
+                                        theSewTolerance ),
+      myIsExtrusionByNormal( false )
+    {
+    }
+    // params for extrusion by normal
+    ExtrusionParams(CORBA::Double  theStepSize,
+                    CORBA::Long    theNbOfSteps,
+                    CORBA::Short   theDim,
+                    CORBA::Boolean theByAverageNormal,
+                    CORBA::Boolean theUseInputElemsOnly,
+                    CORBA::Boolean theMakeGroups ):
+      ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
+                                        theNbOfSteps,
+                                        makeFlags( theMakeGroups,
+                                                   theByAverageNormal, theUseInputElemsOnly ),
+                                        theDim),
+      myIsExtrusionByNormal( true )
+    {
+    }
+
+    void SetNoGroups()
+    {
+      Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
+    }
+  };
 }
 
 //=======================================================================
-//function : RotationSweepMakeGroups
-//purpose  :
+/*!
+ * \brief Generate dim+1 elements by extrusion of elements along vector
+ *  \param [in] edges - edges to extrude: a list including groups, sub-meshes or a mesh
+ *  \param [in] faces - faces to extrude: a list including groups, sub-meshes or a mesh
+ *  \param [in] nodes - nodes to extrude: a list including groups, sub-meshes or a mesh
+ *  \param [in] stepVector - vector giving direction and distance of an extrusion step
+ *  \param [in] nbOfSteps - number of elements to generate from one element
+ *  \param [in] toMakeGroups - if true, new elements will be included into new groups
+ *              corresponding to groups the input elements included in.
+ *  \return ListOfGroups - new groups craeted if \a toMakeGroups is true
+ */
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::RotationSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
-                                            const SMESH::AxisStruct& theAxis,
-                                            CORBA::Double            theAngleInRadians,
-                                            CORBA::Long              theNbOfSteps,
-                                            CORBA::Double            theTolerance)
+SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNodes,
+                                          const SMESH::ListOfIDSources & theEdges,
+                                          const SMESH::ListOfIDSources & theFaces,
+                                          const SMESH::DirStruct &       theStepVector,
+                                          CORBA::Long                    theNbOfSteps,
+                                          CORBA::Boolean                 theToMakeGroups)
+  throw (SALOME::SALOME_Exception)
 {
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
+  SMESH_TRY;
+  initData();
 
-  SMESH::ListOfGroups *aGroups = rotationSweep(theIDsOfElements,
-                                               theAxis,
-                                               theAngleInRadians,
-                                               theNbOfSteps,
-                                               theTolerance,
-                                               true);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".RotationSweepMakeGroups( "
-                << theIDsOfElements        << ", "
-                << theAxis                   << ", "
-                << TVar( theAngleInRadians ) << ", "
-                << TVar( theNbOfSteps      ) << ", "
-                << TVar( theTolerance      ) << " )";
+  ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
+
+  TIDSortedElemSet elemsNodes[2];
+  for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
+    SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
+    while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
   }
-  return aGroups;
-}
+  for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
+    idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
+  for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
+    idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
 
-//=======================================================================
-//function : RotationSweepObject
-//purpose  :
-//=======================================================================
+  TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
+  if ( myIsPreviewMode )
+  {
+    SMDSAbs_ElementType previewType = SMDSAbs_All; //SMDSAbs_Face;
+    // if ( (*elemsNodes.begin())->GetType() == SMDSAbs_Node )
+    //   previewType = SMDSAbs_Edge;
 
-void SMESH_MeshEditor_i::RotationSweepObject(SMESH::SMESH_IDSource_ptr theObject,
-                                             const SMESH::AxisStruct & theAxis,
-                                             CORBA::Double             theAngleInRadians,
-                                             CORBA::Long               theNbOfSteps,
-                                             CORBA::Double             theTolerance)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".RotationSweepObject( "
-                  << theObject << ", "
-                  << theAxis << ", "
-                  << theAngleInRadians << ", "
-                  << theNbOfSteps << ", "
-                  << theTolerance << " )";
+    SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
+    TPreviewMesh * tmpMesh = getPreviewMesh();
+    tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
+    tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
+    workElements = & copyElements[0];
+
+    params.SetNoGroups();
   }
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  rotationSweep(anElementsId,
-                theAxis,
-                theAngleInRadians,
-                theNbOfSteps,
-                theTolerance,
-                false);
-}
+  TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
 
-//=======================================================================
-//function : RotationSweepObject1D
-//purpose  :
-//=======================================================================
+  ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      getEditor().ExtrusionSweep( workElements, params, aHistory );
 
-void SMESH_MeshEditor_i::RotationSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
-                                               const SMESH::AxisStruct & theAxis,
-                                               CORBA::Double             theAngleInRadians,
-                                               CORBA::Long               theNbOfSteps,
-                                               CORBA::Double             theTolerance)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".RotationSweepObject1D( "
-                  << theObject                 << ", "
-                  << theAxis                   << ", "
-                  << TVar( theAngleInRadians ) << ", "
-                  << TVar( theNbOfSteps      ) << ", "
-                  << TVar( theTolerance      ) << " )";
-  }
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  rotationSweep(anElementsId,
-                theAxis,
-                theAngleInRadians,
-                theNbOfSteps,
-                theTolerance,
-                false,
-                SMDSAbs_Edge);
-}
+  SMESH::ListOfGroups * aGroups = theToMakeGroups ? getGroups( groupIds.get()) : 0;
 
-//=======================================================================
-//function : RotationSweepObject2D
-//purpose  :
-//=======================================================================
+  declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
 
-void SMESH_MeshEditor_i::RotationSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
-                                               const SMESH::AxisStruct & theAxis,
-                                               CORBA::Double             theAngleInRadians,
-                                               CORBA::Long               theNbOfSteps,
-                                               CORBA::Double             theTolerance)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".RotationSweepObject2D( "
-                  << theObject                 << ", "
-                  << theAxis                   << ", "
-                  << TVar( theAngleInRadians ) << ", "
-                  << TVar( theNbOfSteps      ) << ", "
-                  << TVar( theTolerance      ) << " )";
+  if ( !myIsPreviewMode )
+  {
+    dumpGroupsList( aPythonDump, aGroups );
+    aPythonDump << this<< ".ExtrusionSweepObjects( "
+                << theNodes             << ", "
+                << theEdges             << ", "
+                << theFaces             << ", "
+                << theStepVector        << ", "
+                << TVar( theNbOfSteps ) << ", "
+                << theToMakeGroups      << " )";
   }
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  rotationSweep(anElementsId,
-                theAxis,
-                theAngleInRadians,
-                theNbOfSteps,
-                theTolerance,
-                false,
-                SMDSAbs_Face);
+
+  return aGroups ? aGroups : new SMESH::ListOfGroups;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
-//function : RotationSweepObjectMakeGroups
+//function : ExtrusionByNormal
 //purpose  :
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::RotationSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                  const SMESH::AxisStruct&  theAxis,
-                                                  CORBA::Double             theAngleInRadians,
-                                                  CORBA::Long               theNbOfSteps,
-                                                  CORBA::Double             theTolerance)
+SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
+                                      CORBA::Double                 stepSize,
+                                      CORBA::Long                   nbOfSteps,
+                                      CORBA::Boolean                byAverageNormal,
+                                      CORBA::Boolean                useInputElemsOnly,
+                                      CORBA::Boolean                makeGroups,
+                                      CORBA::Short                  dim)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
+  initData();
+
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
-                                               theAxis,
-                                               theAngleInRadians,
-                                               theNbOfSteps,
-                                               theTolerance,
-                                               true);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".RotationSweepObjectMakeGroups( "
-                << theObject << ", "
-                << theAxis << ", "
-                << theAngleInRadians << ", "
-                << theNbOfSteps << ", "
-                << theTolerance << " )";
+  ExtrusionParams params( stepSize, nbOfSteps, dim,
+                          byAverageNormal, useInputElemsOnly, makeGroups );
+
+  SMDSAbs_ElementType elemType = ( dim == 1 ? SMDSAbs_Edge : SMDSAbs_Face );
+  if ( objects.length() > 0 && !SMESH::DownCast<SMESH_Mesh_i*>( objects[0] ))
+  {
+    SMESH::array_of_ElementType_var elemTypes = objects[0]->GetTypes();
+    if (( elemTypes->length() == 1 ) &&
+        ( elemTypes[0] == SMESH::EDGE || elemTypes[0] == SMESH::FACE ))
+      elemType = ( SMDSAbs_ElementType ) elemTypes[0];
   }
-  return aGroups;
-}
 
-//=======================================================================
-//function : RotationSweepObject1DMakeGroups
-//purpose  :
-//=======================================================================
+  TIDSortedElemSet elemsNodes[2];
+  for ( int i = 0, nb = objects.length(); i < nb; ++i )
+    idSourceToSet( objects[i], getMeshDS(), elemsNodes[0], elemType );
 
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::RotationSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                    const SMESH::AxisStruct&  theAxis,
-                                                    CORBA::Double             theAngleInRadians,
-                                                    CORBA::Long               theNbOfSteps,
-                                                    CORBA::Double             theTolerance)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
+  TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
+  if ( myIsPreviewMode )
+  {
+    SMDSAbs_ElementType previewType = SMDSAbs_Face;
+    SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
+    TPreviewMesh * tmpMesh = getPreviewMesh( previewType );
+    tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
+    workElements = & copyElements[0];
 
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
-                                               theAxis,
-                                               theAngleInRadians,
-                                               theNbOfSteps,
-                                               theTolerance,
-                                               true,
-                                               SMDSAbs_Edge);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".RotationSweepObject1DMakeGroups( "
-                << theObject                 << ", "
-                << theAxis                   << ", "
-                << TVar( theAngleInRadians ) << ", "
-                << TVar( theNbOfSteps )      << ", "
-                << TVar( theTolerance )      << " )";
+    params.SetNoGroups();
   }
-  return aGroups;
-}
 
-//=======================================================================
-//function : RotationSweepObject2DMakeGroups
-//purpose  :
-//=======================================================================
+  ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      getEditor().ExtrusionSweep( workElements, params, aHistory );
 
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::RotationSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                    const SMESH::AxisStruct&  theAxis,
-                                                    CORBA::Double             theAngleInRadians,
-                                                    CORBA::Long               theNbOfSteps,
-                                                    CORBA::Double             theTolerance)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
+  SMESH::ListOfGroups * aGroups = makeGroups ? getGroups( groupIds.get()) : 0;
 
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups *aGroups = rotationSweep(anElementsId,
-                                               theAxis,
-                                               theAngleInRadians,
-                                               theNbOfSteps,
-                                               theTolerance,
-                                               true,
-                                               SMDSAbs_Face);
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".RotationSweepObject2DMakeGroups( "
-                << theObject                 << ", "
-                << theAxis                   << ", "
-                << TVar( theAngleInRadians ) << ", "
-                << TVar( theNbOfSteps      ) << ", "
-                << TVar( theTolerance      ) << " )";
+    dumpGroupsList(aPythonDump, aGroups);
+    aPythonDump << this << ".ExtrusionByNormal( " << objects
+                << ", " << TVar( stepSize )
+                << ", " << TVar( nbOfSteps )
+                << ", " << byAverageNormal
+                << ", " << useInputElemsOnly
+                << ", " << makeGroups
+                << ", " << dim
+                << " )";
   }
-  return aGroups;
-}
 
+  declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
+
+  return aGroups ? aGroups : new SMESH::ListOfGroups;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
+}
 
 //=======================================================================
-//function : extrusionSweep
+//function : AdvancedExtrusion
 //purpose  :
 //=======================================================================
 
 SMESH::ListOfGroups*
-SMESH_MeshEditor_i::extrusionSweep(const SMESH::long_array & theIDsOfElements,
-                                   const SMESH::DirStruct &  theStepVector,
-                                   CORBA::Long               theNbOfSteps,
-                                   bool                      theMakeGroups,
-                                   const SMDSAbs_ElementType theElementType)
+SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
+                                      const SMESH::DirStruct &  theStepVector,
+                                      CORBA::Long               theNbOfSteps,
+                                      CORBA::Long               theExtrFlags,
+                                      CORBA::Double             theSewTolerance,
+                                      CORBA::Boolean            theMakeGroups)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-  try {
-#ifdef NO_CAS_CATCH
-    OCC_CATCH_SIGNALS;
-#endif
-    TIDSortedElemSet elements, copyElements;
-    arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
-
-    const SMESH::PointStruct * P = &theStepVector.PS;
-    gp_Vec stepVec( P->x, P->y, P->z );
+  TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
 
-    TIDSortedElemSet* workElements = & elements;
+  ExtrusionParams params( theStepVector, theNbOfSteps, theMakeGroups,
+                          theExtrFlags, theSewTolerance );
 
-    SMDSAbs_ElementType aType = SMDSAbs_Face;
-    if (theElementType == SMDSAbs_Node)
-    {
-      aType = SMDSAbs_Edge;
-    }
-    if ( myIsPreviewMode ) {
-      SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
-      getPreviewMesh( aType )->Copy( elements, copyElements, select, avoid );
-      workElements = & copyElements;
-      theMakeGroups = false;
-    }
+  TIDSortedElemSet elemsNodes[2];
+  arrayToSet( theIDsOfElements, getMeshDS(), elemsNodes[0] );
 
-    TElemOfElemListMap aHystory;
-    ::SMESH_MeshEditor::PGroupIDs groupIds = 
-        getEditor().ExtrusionSweep (*workElements, stepVec, theNbOfSteps, aHystory, theMakeGroups);
+  ::SMESH_MeshEditor::TTElemOfElemListMap aHistory;
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      getEditor().ExtrusionSweep( elemsNodes, params, aHistory );
 
-    myMesh->GetMeshDS()->Modified();
+  SMESH::ListOfGroups * aGroups = theMakeGroups ? getGroups( groupIds.get()) : 0;
 
-    return theMakeGroups ? getGroups(groupIds.get()) : 0;
+  declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
 
-  } catch(Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    INFOS( "SMESH_MeshEditor_i::ExtrusionSweep fails - "<< aFail->GetMessageString() );
+  if ( !myIsPreviewMode ) {
+    dumpGroupsList(aPythonDump, aGroups);
+    aPythonDump << this << ".AdvancedExtrusion( "
+                << theIDsOfElements << ", "
+                << theStepVector << ", "
+                << theNbOfSteps << ", "
+                << theExtrFlags << ", "
+                << theSewTolerance << ", "
+                << theMakeGroups << " )";
   }
+
+  return aGroups ? aGroups : new SMESH::ListOfGroups;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
-//=======================================================================
-//function : ExtrusionSweep
-//purpose  :
-//=======================================================================
+//================================================================================
+/*!
+ * \brief Convert extrusion error to IDL enum
+ */
+//================================================================================
 
-void SMESH_MeshEditor_i::ExtrusionSweep(const SMESH::long_array & theIDsOfElements,
-                                        const SMESH::DirStruct &  theStepVector,
-                                        CORBA::Long               theNbOfSteps)
+namespace
 {
-  extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false );
-  if (!myIsPreviewMode) {
-    TPythonDump() << this << ".ExtrusionSweep( "
-                  << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps) << " )";
+#define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
+
+  SMESH::SMESH_MeshEditor::Extrusion_Error convExtrError( ::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 );
+    }
+    return SMESH::SMESH_MeshEditor::EXTR_OK;
   }
 }
 
 //=======================================================================
-//function : ExtrusionSweep0D
+//function : extrusionAlongPath
 //purpose  :
 //=======================================================================
-
-void SMESH_MeshEditor_i::ExtrusionSweep0D(const SMESH::long_array & theIDsOfElements,
-                                          const SMESH::DirStruct &  theStepVector,
-                                          CORBA::Long               theNbOfSteps)
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & theNodes,
+                                              const SMESH::ListOfIDSources & theEdges,
+                                              const SMESH::ListOfIDSources & theFaces,
+                                              SMESH::SMESH_IDSource_ptr      thePathMesh,
+                                              GEOM::GEOM_Object_ptr          thePathShape,
+                                              CORBA::Long                    theNodeStart,
+                                              CORBA::Boolean                 theHasAngles,
+                                              const SMESH::double_array &    theAngles,
+                                              CORBA::Boolean                 theLinearVariation,
+                                              CORBA::Boolean                 theHasRefPoint,
+                                              const SMESH::PointStruct &     theRefPoint,
+                                              bool                           theMakeGroups,
+                                              SMESH::SMESH_MeshEditor::Extrusion_Error& theError)
+  throw (SALOME::SALOME_Exception)
 {
-  extrusionSweep (theIDsOfElements, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
-  if (!myIsPreviewMode) {
-    TPythonDump() << this << ".ExtrusionSweep0D( "
-                  << theIDsOfElements << ", " << theStepVector <<", " << TVar(theNbOfSteps)<< " )";
-  }
-}
+  SMESH_TRY;
+  initData();
 
-//=======================================================================
-//function : ExtrusionSweepObject
-//purpose  :
-//=======================================================================
+  SMESH::ListOfGroups_var aGroups = new SMESH::ListOfGroups;
 
-void SMESH_MeshEditor_i::ExtrusionSweepObject(SMESH::SMESH_IDSource_ptr theObject,
-                                              const SMESH::DirStruct &  theStepVector,
-                                              CORBA::Long               theNbOfSteps)
-{
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false );
-  if (!myIsPreviewMode) {
-    TPythonDump() << this << ".ExtrusionSweepObject( "
-                  << theObject << ", " << theStepVector << ", " << theNbOfSteps << " )";
-  }
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject0D
-//purpose  :
-//=======================================================================
-
-void SMESH_MeshEditor_i::ExtrusionSweepObject0D(SMESH::SMESH_IDSource_ptr theObject,
-                                                const SMESH::DirStruct &  theStepVector,
-                                                CORBA::Long               theNbOfSteps)
-{
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Node );
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".ExtrusionSweepObject0D( "
-                  << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject1D
-//purpose  :
-//=======================================================================
-
-void SMESH_MeshEditor_i::ExtrusionSweepObject1D(SMESH::SMESH_IDSource_ptr theObject,
-                                                const SMESH::DirStruct &  theStepVector,
-                                                CORBA::Long               theNbOfSteps)
-{
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Edge );
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".ExtrusionSweepObject1D( "
-                  << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject2D
-//purpose  :
-//=======================================================================
-
-void SMESH_MeshEditor_i::ExtrusionSweepObject2D(SMESH::SMESH_IDSource_ptr theObject,
-                                                const SMESH::DirStruct &  theStepVector,
-                                                CORBA::Long               theNbOfSteps)
-{
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionSweep (anElementsId, theStepVector, theNbOfSteps, false, SMDSAbs_Face );
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << this << ".ExtrusionSweepObject2D( "
-                  << theObject << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-}
-
-//=======================================================================
-//function : ExtrusionSweepMakeGroups
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepMakeGroups(const SMESH::long_array& theIDsOfElements,
-                                             const SMESH::DirStruct&  theStepVector,
-                                             CORBA::Long              theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true);
-
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepMakeGroups( " << theIDsOfElements
-                << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionSweepMakeGroups0D
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepMakeGroups0D(const SMESH::long_array& theIDsOfElements,
-                                               const SMESH::DirStruct&  theStepVector,
-                                               CORBA::Long              theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::ListOfGroups* aGroups = extrusionSweep(theIDsOfElements, theStepVector, theNbOfSteps, true,SMDSAbs_Node);
-
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepMakeGroups0D( " << theIDsOfElements
-                << ", " << theStepVector <<", " << TVar( theNbOfSteps ) << " )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionSweepObjectMakeGroups
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                   const SMESH::DirStruct&   theStepVector,
-                                                   CORBA::Long               theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector, theNbOfSteps, true);
-
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepObjectMakeGroups( " << theObject
-                << ", " << theStepVector << ", " << theNbOfSteps << " )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject0DMakeGroups
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepObject0DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                     const SMESH::DirStruct&   theStepVector,
-                                                     CORBA::Long               theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Node);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepObject0DMakeGroups( " << theObject
-                << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject1DMakeGroups
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepObject1DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                     const SMESH::DirStruct&   theStepVector,
-                                                     CORBA::Long               theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Edge);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepObject1DMakeGroups( " << theObject
-                << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionSweepObject2DMakeGroups
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionSweepObject2DMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
-                                                     const SMESH::DirStruct&   theStepVector,
-                                                     CORBA::Long               theNbOfSteps)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionSweep(anElementsId, theStepVector,
-                                                 theNbOfSteps, true, SMDSAbs_Face);
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".ExtrusionSweepObject2DMakeGroups( " << theObject
-                << ", " << theStepVector << ", " << TVar( theNbOfSteps ) << " )";
-  }
-  return aGroups;
-}
-
-
-//=======================================================================
-//function : advancedExtrusion
-//purpose  :
-//=======================================================================
-
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::advancedExtrusion(const SMESH::long_array & theIDsOfElements,
-                                      const SMESH::DirStruct &  theStepVector,
-                                      CORBA::Long               theNbOfSteps,
-                                      CORBA::Long               theExtrFlags,
-                                      CORBA::Double             theSewTolerance,
-                                      const bool                theMakeGroups)
-{
-  initData();
-
-  TIDSortedElemSet elements;
-  arrayToSet(theIDsOfElements, getMeshDS(), elements);
-
-  const SMESH::PointStruct * P = &theStepVector.PS;
-  gp_Vec stepVec( P->x, P->y, P->z );
-
-  TElemOfElemListMap aHystory;
-  ::SMESH_MeshEditor::PGroupIDs groupIds =
-      getEditor().ExtrusionSweep (elements, stepVec, theNbOfSteps, aHystory,
-                                  theMakeGroups, theExtrFlags, theSewTolerance);
-
-  return theMakeGroups ? getGroups(groupIds.get()) : 0;
-}
-
-//=======================================================================
-//function : AdvancedExtrusion
-//purpose  :
-//=======================================================================
-
-void SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements,
-                                           const SMESH::DirStruct &  theStepVector,
-                                           CORBA::Long               theNbOfSteps,
-                                           CORBA::Long               theExtrFlags,
-                                           CORBA::Double             theSewTolerance)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << "stepVector = " << theStepVector;
-    TPythonDump() << this << ".AdvancedExtrusion("
-                  << theIDsOfElements
-                  << ", stepVector, "
-                  << theNbOfSteps << ","
-                  << theExtrFlags << ", "
-                  << theSewTolerance <<  " )";
-  }
-  advancedExtrusion( theIDsOfElements,
-                     theStepVector,
-                     theNbOfSteps,
-                     theExtrFlags,
-                     theSewTolerance,
-                     false);
-}
-
-//=======================================================================
-//function : AdvancedExtrusionMakeGroups
-//purpose  :
-//=======================================================================
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::AdvancedExtrusionMakeGroups(const SMESH::long_array& theIDsOfElements,
-                                                const SMESH::DirStruct&  theStepVector,
-                                                CORBA::Long              theNbOfSteps,
-                                                CORBA::Long              theExtrFlags,
-                                                CORBA::Double            theSewTolerance)
-{
-  if (!myIsPreviewMode) {
-    TPythonDump() << "stepVector = " << theStepVector;
-  }
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::ListOfGroups * aGroups = advancedExtrusion( theIDsOfElements,
-                                                     theStepVector,
-                                                     theNbOfSteps,
-                                                     theExtrFlags,
-                                                     theSewTolerance,
-                                                     true);
-
-  if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
-    aPythonDump << this << ".AdvancedExtrusionMakeGroups("
-                << theIDsOfElements
-                << ", stepVector, "
-                << theNbOfSteps << ","
-                << theExtrFlags << ", "
-                << theSewTolerance <<  " )";
-  }
-  return aGroups;
-}
+  theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
+  if ( thePathMesh->_is_nil() )
+    return aGroups._retn();
 
-
-//================================================================================
-/*!
- * \brief Convert extrusion error to IDL enum
- */
-//================================================================================
-
-#define RETCASE(enm) case ::SMESH_MeshEditor::enm: return SMESH::SMESH_MeshEditor::enm;
-
-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 );
-  }
-  return SMESH::SMESH_MeshEditor::EXTR_OK;
-}
-
-
-//=======================================================================
-//function : extrusionAlongPath
-//purpose  :
-//=======================================================================
-SMESH::ListOfGroups*
-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,
-                                       const bool                  theMakeGroups,
-                                       SMESH::SMESH_MeshEditor::Extrusion_Error & theError,
-                                       const SMDSAbs_ElementType   theElementType)
-{
-  MESSAGE("extrusionAlongPath");
-  initData();
-
-  if ( thePathMesh->_is_nil() || thePathShape->_is_nil() ) {
-    theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-    return 0;
-  }
+  // get a sub-mesh
+  SMESH_subMesh* aSubMesh = 0;
   SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( thePathMesh );
-
-  TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
-  SMESH_subMesh* aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
-
-  if ( !aSubMesh || !aSubMesh->GetSubMeshDS()) {
-    theError = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-    return 0;
+  if ( thePathShape->_is_nil() )
+  {
+    // thePathMesh should be either a sub-mesh or a mesh with 1D elements only
+    if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( thePathMesh ))
+    {
+      SMESH::SMESH_Mesh_var mesh = thePathMesh->GetMesh();
+      aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+      if ( !aMeshImp ) return aGroups._retn();
+      aSubMesh = aMeshImp->GetImpl().GetSubMeshContaining( sm->GetId() );
+      if ( !aSubMesh ) return aGroups._retn();
+    }
+    else if ( !aMeshImp ||
+              aMeshImp->NbEdges() != aMeshImp->NbElements() )
+    {
+      return aGroups._retn();
+    }
+  }
+  else
+  {
+    if ( !aMeshImp ) return aGroups._retn();
+    TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( thePathShape );
+    aSubMesh = aMeshImp->GetImpl().GetSubMesh( aShape );
+    if ( !aSubMesh || !aSubMesh->GetSubMeshDS() )
+      return aGroups._retn();
   }
 
-  SMDS_MeshNode* nodeStart = (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
+  SMDS_MeshNode* nodeStart =
+    (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(theNodeStart);
   if ( !nodeStart ) {
     theError = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
-    return 0;
+    return aGroups._retn();
   }
 
-  TIDSortedElemSet elements;
-  arrayToSet(theIDsOfElements, getMeshDS(), elements, theElementType);
+  TIDSortedElemSet elemsNodes[2];
+  for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
+    SMDS_ElemIteratorPtr nIt = myMesh_i->GetElements( theNodes[i], SMESH::NODE );
+    while ( nIt->more() ) elemsNodes[1].insert( nIt->next() );
+  }
+  for ( int i = 0, nb = theEdges.length(); i < nb; ++i )
+    idSourceToSet( theEdges[i], getMeshDS(), elemsNodes[0], SMDSAbs_Edge );
+  for ( int i = 0, nb = theFaces.length(); i < nb; ++i )
+    idSourceToSet( theFaces[i], getMeshDS(), elemsNodes[0], SMDSAbs_Face );
 
   list<double> angles;
   for (int i = 0; i < theAngles.length(); i++) {
@@ -2749,628 +2791,66 @@ SMESH_MeshEditor_i::extrusionAlongPath(const SMESH::long_array &   theIDsOfEleme
 
   int nbOldGroups = myMesh->NbGroup();
 
-  ::SMESH_MeshEditor::Extrusion_Error error =
-      getEditor().ExtrusionAlongTrack( elements, aSubMesh, nodeStart,
-                                    theHasAngles, angles, false,
-                                    theHasRefPoint, refPnt, theMakeGroups );
-  myMesh->GetMeshDS()->Modified();
-  theError = convExtrError( error );
-
-  if ( theMakeGroups ) {
-    list<int> groupIDs = myMesh->GetGroupIds();
-    list<int>::iterator newBegin = groupIDs.begin();
-    std::advance( newBegin, nbOldGroups ); // skip old groups
-    groupIDs.erase( groupIDs.begin(), newBegin );
-    return getGroups( & groupIDs );
-  }
-  return 0;
-}
-
-
-//=======================================================================
-//function : extrusionAlongPathX
-//purpose  :
-//=======================================================================
-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,
-                                        bool                       MakeGroups,
-                                        const SMDSAbs_ElementType  ElementType,
-                                        SMESH::SMESH_MeshEditor::Extrusion_Error & Error)
-{
-  SMESH::ListOfGroups* EmptyGr = new SMESH::ListOfGroups;
-
-  initData();
-
-  list<double> angles;
-  for (int i = 0; i < Angles.length(); i++) {
-    angles.push_back( Angles[i] );
-  }
-  gp_Pnt refPnt( RefPoint.x, RefPoint.y, RefPoint.z );
-  int nbOldGroups = myMesh->NbGroup();
-
-  if ( Path->_is_nil() ) {
-    Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-    return EmptyGr;
-  }
-
-  TIDSortedElemSet elements, copyElements;
-  arrayToSet(IDsOfElements, getMeshDS(), elements, ElementType);
-
-  TIDSortedElemSet* workElements = &elements;
-
+  TIDSortedElemSet* workElements = & elemsNodes[0], copyElements[2];
   if ( myIsPreviewMode )
   {
     SMDSAbs_ElementType select = SMDSAbs_All, avoid = SMDSAbs_Volume;
-    getPreviewMesh( SMDSAbs_Face )->Copy( elements, copyElements, select, avoid );
-    workElements = & copyElements;
-    MakeGroups = false;
+    TPreviewMesh * tmpMesh = getPreviewMesh();
+    tmpMesh->Copy( elemsNodes[0], copyElements[0], select, avoid );
+    tmpMesh->Copy( elemsNodes[1], copyElements[1], select, avoid );
+    workElements = & copyElements[0];
+    theMakeGroups = false;
   }
 
   ::SMESH_MeshEditor::Extrusion_Error error;
-
-  if ( SMESH_Mesh_i* aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( Path ))
-  {
-    // path as mesh
-    SMDS_MeshNode* aNodeStart =
-      (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
-    if ( !aNodeStart ) {
-      Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
-      return EmptyGr;
-    }
-    error = getEditor().ExtrusionAlongTrack( *workElements, &(aMeshImp->GetImpl()), aNodeStart,
-                                             HasAngles, angles, LinearVariation,
-                                             HasRefPoint, refPnt, MakeGroups );
-    myMesh->GetMeshDS()->Modified();
-  }
-  else if ( SMESH_subMesh_i* aSubMeshImp = SMESH::DownCast<SMESH_subMesh_i*>( Path ))
-  {
-    // path as submesh
-    SMESH::SMESH_Mesh_ptr aPathMesh = aSubMeshImp->GetFather();
-    aMeshImp = SMESH::DownCast<SMESH_Mesh_i*>( aPathMesh );
-    SMDS_MeshNode* aNodeStart =
-      (SMDS_MeshNode*)aMeshImp->GetImpl().GetMeshDS()->FindNode(NodeStart);
-    if ( !aNodeStart ) {
-      Error = SMESH::SMESH_MeshEditor::EXTR_BAD_STARTING_NODE;
-      return EmptyGr;
-    }
-    SMESH_subMesh* aSubMesh =
-      aMeshImp->GetImpl().GetSubMeshContaining(aSubMeshImp->GetId());
-    error = getEditor().ExtrusionAlongTrack( *workElements, aSubMesh, aNodeStart,
-                                             HasAngles, angles, LinearVariation,
-                                             HasRefPoint, refPnt, MakeGroups );
-    myMesh->GetMeshDS()->Modified();
-  }
-  else if ( SMESH::DownCast<SMESH_Group_i*>( Path ))
-  {
-    // path as group of 1D elements
-    // ????????
-  }
+  if ( !aSubMesh )
+    error = getEditor().ExtrusionAlongTrack( workElements, &(aMeshImp->GetImpl()), nodeStart,
+                                             theHasAngles, angles, theLinearVariation,
+                                             theHasRefPoint, refPnt, theMakeGroups );
   else
-  {
-    // invalid path
-    Error = SMESH::SMESH_MeshEditor::EXTR_BAD_PATH_SHAPE;
-    return EmptyGr;
-  }
+    error = getEditor().ExtrusionAlongTrack( workElements, aSubMesh, nodeStart,
+                                             theHasAngles, angles, theLinearVariation,
+                                             theHasRefPoint, refPnt, theMakeGroups );
 
-  Error = convExtrError( error );
+  declareMeshModified( /*isReComputeSafe=*/true );
+  theError = convExtrError( error );
 
-  if ( MakeGroups ) {
+  TPythonDump aPythonDump; // it is here to prevent dump of getGroups()
+  if ( theMakeGroups ) {
     list<int> groupIDs = myMesh->GetGroupIds();
     list<int>::iterator newBegin = groupIDs.begin();
     std::advance( newBegin, nbOldGroups ); // skip old groups
     groupIDs.erase( groupIDs.begin(), newBegin );
-    return getGroups( & groupIDs );
+    aGroups = getGroups( & groupIDs );
+    if ( ! &aGroups.in() ) aGroups = new SMESH::ListOfGroups;
   }
-  return EmptyGr;
-}
-
 
-//=======================================================================
-//function : ExtrusionAlongPath
-//purpose  :
-//=======================================================================
-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)
-{
-  MESSAGE("ExtrusionAlongPath");
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << "error = " << this << ".ExtrusionAlongPath( "
-                  << theIDsOfElements << ", "
-                  << thePathMesh      << ", "
-                  << thePathShape     << ", "
-                  << theNodeStart     << ", "
-                  << theHasAngles     << ", "
-                  << theAngles        << ", "
-                  << theHasRefPoint   << ", "
-                  << "SMESH.PointStruct( "
-                  << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  SMESH::SMESH_MeshEditor::Extrusion_Error anError;
-  extrusionAlongPath( theIDsOfElements,
-                      thePathMesh,
-                      thePathShape,
-                      theNodeStart,
-                      theHasAngles,
-                      theAngles,
-                      theHasRefPoint,
-                      theRefPoint,
-                      false,
-                      anError);
-  return anError;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObject
-//purpose  :
-//=======================================================================
-SMESH::SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor_i::ExtrusionAlongPathObject(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)
-{
   if ( !myIsPreviewMode ) {
-    TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject( "
-                  << theObject        << ", "
-                  << thePathMesh      << ", "
-                  << thePathShape     << ", "
-                  << theNodeStart     << ", "
-                  << theHasAngles     << ", "
-                  << theAngles        << ", "
-                  << theHasRefPoint   << ", "
-                  << "SMESH.PointStruct( "
-                  << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  SMESH::SMESH_MeshEditor::Extrusion_Error anError;
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionAlongPath( anElementsId,
-                      thePathMesh,
-                      thePathShape,
-                      theNodeStart,
-                      theHasAngles,
-                      theAngles,
-                      theHasRefPoint,
-                      theRefPoint,
-                      false,
-                      anError);
-  return anError;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObject1D
-//purpose  :
-//=======================================================================
-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)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject1D( "
-                  << theObject        << ", "
-                  << thePathMesh      << ", "
-                  << thePathShape     << ", "
-                  << theNodeStart     << ", "
-                  << theHasAngles     << ", "
-                  << theAngles        << ", "
-                  << theHasRefPoint   << ", "
-                  << "SMESH.PointStruct( "
-                  << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  SMESH::SMESH_MeshEditor::Extrusion_Error anError;
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionAlongPath( anElementsId,
-                      thePathMesh,
-                      thePathShape,
-                      theNodeStart,
-                      theHasAngles,
-                      theAngles,
-                      theHasRefPoint,
-                      theRefPoint,
-                      false,
-                      anError,
-                      SMDSAbs_Edge);
-  return anError;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObject2D
-//purpose  :
-//=======================================================================
-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)
-{
-  if ( !myIsPreviewMode ) {
-    TPythonDump() << "error = " << this << ".ExtrusionAlongPathObject2D( "
-                  << theObject        << ", "
-                  << thePathMesh      << ", "
-                  << thePathShape     << ", "
-                  << theNodeStart     << ", "
-                  << theHasAngles     << ", "
-                  << theAngles        << ", "
-                  << theHasRefPoint   << ", "
-                  << "SMESH.PointStruct( "
-                  << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                  << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  SMESH::SMESH_MeshEditor::Extrusion_Error anError;
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  extrusionAlongPath( anElementsId,
-                      thePathMesh,
-                      thePathShape,
-                      theNodeStart,
-                      theHasAngles,
-                      theAngles,
-                      theHasRefPoint,
-                      theRefPoint,
-                      false,
-                      anError,
-                      SMDSAbs_Face);
-  return anError;
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongPathMakeGroups
-//purpose  :
-//=======================================================================
-SMESH::ListOfGroups*
-SMESH_MeshEditor_i::ExtrusionAlongPathMakeGroups(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::SMESH_MeshEditor::Extrusion_Error& Error)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::ListOfGroups * aGroups =  extrusionAlongPath( theIDsOfElements,
-                                                       thePathMesh,
-                                                       thePathShape,
-                                                       theNodeStart,
-                                                       theHasAngles,
-                                                       theAngles,
-                                                       theHasRefPoint,
-                                                       theRefPoint,
-                                                       true,
-                                                       Error);
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << aGroups << ", error)";
-    else
-      aPythonDump <<"error";
-
-    aPythonDump<<" = "<< this << ".ExtrusionAlongPathMakeGroups( "
-               << theIDsOfElements << ", "
-               << thePathMesh      << ", "
-               << thePathShape     << ", "
-               << theNodeStart     << ", "
-               << theHasAngles     << ", "
-               << theAngles        << ", "
-               << theHasRefPoint   << ", "
-               << "SMESH.PointStruct( "
-               << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-               << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObjectMakeGroups
-//purpose  :
-//=======================================================================
-SMESH::ListOfGroups* SMESH_MeshEditor_i::
-ExtrusionAlongPathObjectMakeGroups(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)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
-                                                      thePathMesh,
-                                                      thePathShape,
-                                                      theNodeStart,
-                                                      theHasAngles,
-                                                      theAngles,
-                                                      theHasRefPoint,
-                                                      theRefPoint,
-                                                      true,
-                                                      Error);
-
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << aGroups << ", error)";
-    else
-      aPythonDump <<"error";
-
-    aPythonDump << " = " << this << ".ExtrusionAlongPathObjectMakeGroups( "
-                << theObject << ", "
-                << thePathMesh      << ", "
-                << thePathShape     << ", "
-                << theNodeStart     << ", "
-                << theHasAngles     << ", "
-                << theAngles        << ", "
-                << theHasRefPoint   << ", "
+    aPythonDump << "(" << aGroups << ", error) = "
+                << this << ".ExtrusionAlongPathObjects( "
+                << theNodes            << ", "
+                << theEdges            << ", "
+                << theFaces            << ", "
+                << thePathMesh         << ", "
+                << thePathShape        << ", "
+                << theNodeStart        << ", "
+                << theHasAngles        << ", "
+                << theAngles           << ", "
+                << theLinearVariation  << ", "
+                << theHasRefPoint      << ", "
                 << "SMESH.PointStruct( "
                 << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
                 << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
+                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
+                << theMakeGroups       << " )";
   }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObject1DMakeGroups
-//purpose  :
-//=======================================================================
-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)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
-                                                      thePathMesh,
-                                                      thePathShape,
-                                                      theNodeStart,
-                                                      theHasAngles,
-                                                      theAngles,
-                                                      theHasRefPoint,
-                                                      theRefPoint,
-                                                      true,
-                                                      Error,
-                                                      SMDSAbs_Edge);
 
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << aGroups << ", error)";
-    else
-      aPythonDump << "error";
+  return aGroups._retn();
 
-    aPythonDump << " = " << this << ".ExtrusionAlongPathObject1DMakeGroups( "
-                << theObject << ", "
-                << thePathMesh      << ", "
-                << thePathShape     << ", "
-                << theNodeStart     << ", "
-                << theHasAngles     << ", "
-                << theAngles        << ", "
-                << theHasRefPoint   << ", "
-                << "SMESH.PointStruct( "
-                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  return aGroups;
-}
-
-//=======================================================================
-//function : ExtrusionAlongPathObject2DMakeGroups
-//purpose  :
-//=======================================================================
-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)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = theObject->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionAlongPath( anElementsId,
-                                                      thePathMesh,
-                                                      thePathShape,
-                                                      theNodeStart,
-                                                      theHasAngles,
-                                                      theAngles,
-                                                      theHasRefPoint,
-                                                      theRefPoint,
-                                                      true,
-                                                      Error,
-                                                      SMDSAbs_Face);
-
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << aGroups << ", error)";
-    else
-      aPythonDump << "error";
-
-    aPythonDump << " = " << this << ".ExtrusionAlongPathObject2DMakeGroups( "
-                << theObject << ", "
-                << thePathMesh      << ", "
-                << thePathShape     << ", "
-                << theNodeStart     << ", "
-                << theHasAngles     << ", "
-                << theAngles        << ", "
-                << theHasRefPoint   << ", "
-                << "SMESH.PointStruct( "
-                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ) )";
-  }
-  return aGroups;
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongPathObjX
-//purpose  :
-//=======================================================================
-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)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::long_array_var anElementsId = Object->GetIDs();
-  SMESH::ListOfGroups * aGroups = extrusionAlongPathX(anElementsId,
-                                                      Path,
-                                                      NodeStart,
-                                                      HasAngles,
-                                                      Angles,
-                                                      LinearVariation,
-                                                      HasRefPoint,
-                                                      RefPoint,
-                                                      MakeGroups,
-                                                      (SMDSAbs_ElementType)ElemType,
-                                                      Error);
-
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << *aGroups << ", error)";
-    else
-      aPythonDump << "error";
-
-    aPythonDump << " = " << this << ".ExtrusionAlongPathObjX( "
-                << Object          << ", "
-                << Path            << ", "
-                << NodeStart       << ", "
-                << HasAngles       << ", "
-                << TVar( Angles )  << ", "
-                << LinearVariation << ", "
-                << HasRefPoint     << ", "
-                << "SMESH.PointStruct( "
-                << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
-                << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
-                << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
-                << MakeGroups << ", "
-                << ElemType << " )";
-  }
-  return aGroups;
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongPathX
-//purpose  :
-//=======================================================================
-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)
-{
-  TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
-
-  SMESH::ListOfGroups * aGroups = extrusionAlongPathX(IDsOfElements,
-                                                      Path,
-                                                      NodeStart,
-                                                      HasAngles,
-                                                      Angles,
-                                                      LinearVariation,
-                                                      HasRefPoint,
-                                                      RefPoint,
-                                                      MakeGroups,
-                                                      (SMDSAbs_ElementType)ElemType,
-                                                      Error);
-
-  if (!myIsPreviewMode) {
-    bool isDumpGroups = aGroups && aGroups->length() > 0;
-    if (isDumpGroups)
-      aPythonDump << "(" << *aGroups << ", error)";
-    else
-      aPythonDump <<"error";
-
-    aPythonDump << " = " << this << ".ExtrusionAlongPathX( "
-                << IDsOfElements   << ", "
-                << Path            << ", "
-                << NodeStart       << ", "
-                << HasAngles       << ", "
-                << TVar( Angles )  << ", "
-                << LinearVariation << ", "
-                << HasRefPoint     << ", "
-                << "SMESH.PointStruct( "
-                << TVar( HasRefPoint ? RefPoint.x : 0 ) << ", "
-                << TVar( HasRefPoint ? RefPoint.y : 0 ) << ", "
-                << TVar( HasRefPoint ? RefPoint.z : 0 ) << " ), "
-                << MakeGroups << ", "
-                << ElemType << " )";
-  }
-  return aGroups;
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
-
 //================================================================================
 /*!
  * \brief Compute rotation angles for ExtrusionAlongPath as linear variation
@@ -3442,7 +2922,6 @@ SMESH_MeshEditor_i::LinearAnglesVariation(SMESH::SMESH_Mesh_ptr       thePathMes
   return aResult._retn();
 }
 
-
 //=======================================================================
 //function : mirror
 //purpose  :
@@ -3455,7 +2934,9 @@ SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
                            CORBA::Boolean                      theCopy,
                            bool                                theMakeGroups,
                            ::SMESH_Mesh*                       theTargetMesh)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   gp_Pnt P ( theAxis.x, theAxis.y, theAxis.z );
@@ -3504,11 +2985,13 @@ SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
     }
     else
     {
-      myMesh->GetMeshDS()->Modified();
-      myMesh->SetIsModified( true );
+      declareMeshModified( /*isReComputeSafe=*/false );
     }
   }
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -3520,6 +3003,7 @@ void SMESH_MeshEditor_i::Mirror(const SMESH::long_array &           theIDsOfElem
                                 const SMESH::AxisStruct &           theAxis,
                                 SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
                                 CORBA::Boolean                      theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".Mirror( "
@@ -3546,6 +3030,7 @@ void SMESH_MeshEditor_i::MirrorObject(SMESH::SMESH_IDSource_ptr           theObj
                                       const SMESH::AxisStruct &           theAxis,
                                       SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
                                       CORBA::Boolean                      theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".MirrorObject( "
@@ -3571,6 +3056,7 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsOfElements,
                                      const SMESH::AxisStruct&            theMirror,
                                      SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -3582,7 +3068,7 @@ SMESH_MeshEditor_i::MirrorMakeGroups(const SMESH::long_array&            theIDsO
     aGroups = mirror(elements, theMirror, theMirrorType, true, true);
   }
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".MirrorMakeGroups( "
                 << theIDsOfElements              << ", "
                 << theMirror                     << ", "
@@ -3600,6 +3086,7 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           theObject,
                                            const SMESH::AxisStruct&            theMirror,
                                            SMESH::SMESH_MeshEditor::MirrorType theMirrorType)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -3610,7 +3097,7 @@ SMESH_MeshEditor_i::MirrorObjectMakeGroups(SMESH::SMESH_IDSource_ptr           t
 
   if (!myIsPreviewMode)
   {
-    DumpGroupsList(aPythonDump,aGroups);
+    dumpGroupsList(aPythonDump,aGroups);
     aPythonDump << this << ".MirrorObjectMakeGroups( "
                 << theObject                     << ", "
                 << theMirror                     << ", "
@@ -3630,6 +3117,7 @@ SMESH_MeshEditor_i::MirrorMakeMesh(const SMESH::long_array&            theIDsOfE
                                    SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
                                    CORBA::Boolean                      theCopyGroups,
                                    const char*                         theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
@@ -3677,6 +3165,7 @@ SMESH_MeshEditor_i::MirrorObjectMakeMesh(SMESH::SMESH_IDSource_ptr           the
                                          SMESH::SMESH_MeshEditor::MirrorType theMirrorType,
                                          CORBA::Boolean                      theCopyGroups,
                                          const char*                         theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
@@ -3723,7 +3212,9 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
                               CORBA::Boolean            theCopy,
                               bool                      theMakeGroups,
                               ::SMESH_Mesh*             theTargetMesh)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   if ( theTargetMesh )
@@ -3761,12 +3252,14 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
     }
     else
     {
-      myMesh->GetMeshDS()->Modified();
-      myMesh->SetIsModified( true );
+      declareMeshModified( /*isReComputeSafe=*/false );
     }
   }
 
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -3777,6 +3270,7 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
 void SMESH_MeshEditor_i::Translate(const SMESH::long_array & theIDsOfElements,
                                    const SMESH::DirStruct &  theVector,
                                    CORBA::Boolean            theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".Translate( "
@@ -3799,6 +3293,7 @@ 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)
+  throw (SALOME::SALOME_Exception)
 {
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".TranslateObject( "
@@ -3809,7 +3304,7 @@ void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
   TIDSortedElemSet elements;
 
   bool emptyIfIsMesh = myIsPreviewMode ? false : true;
-  
+
   if (idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, emptyIfIsMesh))
     translate(elements, theVector, theCopy, false);
 }
@@ -3822,6 +3317,7 @@ void SMESH_MeshEditor_i::TranslateObject(SMESH::SMESH_IDSource_ptr theObject,
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElements,
                                         const SMESH::DirStruct&  theVector)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -3832,7 +3328,7 @@ SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElement
     aGroups = translate(elements,theVector,true,true);
   }
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".TranslateMakeGroups( "
                 << theIDsOfElements << ", "
                 << theVector        << " )";
@@ -3848,6 +3344,7 @@ SMESH_MeshEditor_i::TranslateMakeGroups(const SMESH::long_array& theIDsOfElement
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
                                               const SMESH::DirStruct&   theVector)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -3857,7 +3354,7 @@ SMESH_MeshEditor_i::TranslateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObjec
     aGroups = translate(elements, theVector, true, true);
 
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".TranslateObjectMakeGroups( "
                 << theObject << ", "
                 << theVector << " )";
@@ -3875,6 +3372,7 @@ SMESH_MeshEditor_i::TranslateMakeMesh(const SMESH::long_array& theIDsOfElements,
                                       const SMESH::DirStruct&  theVector,
                                       CORBA::Boolean           theCopyGroups,
                                       const char*              theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
@@ -3921,7 +3419,9 @@ SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
                                             const SMESH::DirStruct&   theVector,
                                             CORBA::Boolean            theCopyGroups,
                                             const char*               theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
   { // open new scope to dump "MakeMesh" command
@@ -3933,7 +3433,7 @@ SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
 
     TIDSortedElemSet elements;
     if ( mesh_i &&
-      idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
+         idSourceToSet(theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
     {
       translate(elements, theVector,false, theCopyGroups, & mesh_i->GetImpl());
       mesh_i->CreateGroupServants();
@@ -3952,6 +3452,9 @@ SMESH_MeshEditor_i::TranslateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
     mesh_i->GetGroups();
 
   return mesh._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -3966,7 +3469,9 @@ SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
                            CORBA::Boolean            theCopy,
                            bool                      theMakeGroups,
                            ::SMESH_Mesh*             theTargetMesh)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   if ( theTargetMesh )
@@ -3998,18 +3503,14 @@ SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
 
   if ( theCopy && !myIsPreviewMode)
   {
-    if ( theTargetMesh )
-    {
-      theTargetMesh->GetMeshDS()->Modified();
-    }
-    else
-    {
-      myMesh->GetMeshDS()->Modified();
-      myMesh->SetIsModified( true );
-    }
+    if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
+    else                 declareMeshModified( /*isReComputeSafe=*/false );
   }
 
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4021,6 +3522,7 @@ void SMESH_MeshEditor_i::Rotate(const SMESH::long_array & theIDsOfElements,
                                 const SMESH::AxisStruct & theAxis,
                                 CORBA::Double             theAngle,
                                 CORBA::Boolean            theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if (!myIsPreviewMode) {
     TPythonDump() << this << ".Rotate( "
@@ -4046,6 +3548,7 @@ void SMESH_MeshEditor_i::RotateObject(SMESH::SMESH_IDSource_ptr theObject,
                                       const SMESH::AxisStruct & theAxis,
                                       CORBA::Double             theAngle,
                                       CORBA::Boolean            theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".RotateObject( "
@@ -4069,6 +3572,7 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
                                      const SMESH::AxisStruct& theAxis,
                                      CORBA::Double            theAngle)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -4080,7 +3584,7 @@ SMESH_MeshEditor_i::RotateMakeGroups(const SMESH::long_array& theIDsOfElements,
     aGroups = rotate(elements,theAxis,theAngle,true,true);
   }
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".RotateMakeGroups( "
                 << theIDsOfElements << ", "
                 << theAxis          << ", "
@@ -4098,6 +3602,7 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
                                            const SMESH::AxisStruct&  theAxis,
                                            CORBA::Double             theAngle)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
@@ -4107,7 +3612,7 @@ SMESH_MeshEditor_i::RotateObjectMakeGroups(SMESH::SMESH_IDSource_ptr theObject,
     aGroups = rotate(elements, theAxis, theAngle, true, true);
 
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".RotateObjectMakeGroups( "
                 << theObject        << ", "
                 << theAxis          << ", "
@@ -4127,7 +3632,9 @@ SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
                                    CORBA::Double            theAngleInRadians,
                                    CORBA::Boolean           theCopyGroups,
                                    const char*              theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::SMESH_Mesh_var mesh;
   SMESH_Mesh_i* mesh_i;
 
@@ -4162,6 +3669,9 @@ SMESH_MeshEditor_i::RotateMakeMesh(const SMESH::long_array& theIDsOfElements,
     mesh_i->GetGroups();
 
   return mesh._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4175,7 +3685,9 @@ SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
                                          CORBA::Double             theAngleInRadians,
                                          CORBA::Boolean            theCopyGroups,
                                          const char*               theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::SMESH_Mesh_var mesh;
   SMESH_Mesh_i* mesh_i;
 
@@ -4209,6 +3721,9 @@ SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
     mesh_i->GetGroups();
 
   return mesh._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4223,7 +3738,9 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
                           CORBA::Boolean             theCopy,
                           bool                       theMakeGroups,
                           ::SMESH_Mesh*              theTargetMesh)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
   if ( theScaleFact.length() < 1 )
     THROW_SALOME_CORBA_EXCEPTION("Scale factor not given", SALOME::BAD_PARAM);
@@ -4245,9 +3762,23 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
   };
   double tol = std::numeric_limits<double>::max();
   gp_Trsf aTrsf;
+
+#if OCC_VERSION_LARGE > 0x06070100
+  // fight against ortagonalization
+  // aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
+  //                  0,    S[1], 0,    thePoint.y * (1-S[1]),
+  //                  0,    0,    S[2], thePoint.z * (1-S[2]) );
+  aTrsf.SetTranslation( gp_Vec( thePoint.x * (1-S[0]),
+                                thePoint.y * (1-S[1]),
+                                thePoint.z * (1-S[2])));
+  gp_Mat & M = ( gp_Mat& ) aTrsf.HVectorialPart();
+  M.SetDiagonal( S[0], S[1], S[2] );
+
+#else
   aTrsf.SetValues( S[0], 0,    0,    thePoint.x * (1-S[0]),
                    0,    S[1], 0,    thePoint.y * (1-S[1]),
                    0,    0,    S[2], thePoint.z * (1-S[2]),   tol, tol);
+#endif
 
   TIDSortedElemSet  copyElements;
   TIDSortedElemSet* workElements = &elements;
@@ -4270,18 +3801,13 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
 
   if ( theCopy && !myIsPreviewMode )
   {
-    if ( theTargetMesh )
-    {
-      theTargetMesh->GetMeshDS()->Modified();
-    }
-    else
-    {
-      myMesh->GetMeshDS()->Modified();
-      myMesh->SetIsModified( true );
-    }
+    if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
+    else                 declareMeshModified( /*isReComputeSafe=*/false );
   }
-
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4293,6 +3819,7 @@ void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
                                const SMESH::PointStruct&  thePoint,
                                const SMESH::double_array& theScaleFact,
                                CORBA::Boolean             theCopy)
+  throw (SALOME::SALOME_Exception)
 {
   if ( !myIsPreviewMode ) {
     TPythonDump() << this << ".Scale( "
@@ -4314,12 +3841,13 @@ SMESH::ListOfGroups*
 SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
                                     const SMESH::PointStruct&  thePoint,
                                     const SMESH::double_array& theScaleFact)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump aPythonDump; // it is here to prevent dump of GetGroups()
 
   SMESH::ListOfGroups * aGroups = scale(theObject, thePoint, theScaleFact, true, true);
   if (!myIsPreviewMode) {
-    DumpGroupsList(aPythonDump, aGroups);
+    dumpGroupsList(aPythonDump, aGroups);
     aPythonDump << this << ".Scale("
                 << theObject            << ","
                 << thePoint             << ","
@@ -4340,6 +3868,7 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
                                   const SMESH::double_array& theScaleFact,
                                   CORBA::Boolean             theCopyGroups,
                                   const char*                theMeshName)
+  throw (SALOME::SALOME_Exception)
 {
   SMESH_Mesh_i* mesh_i;
   SMESH::SMESH_Mesh_var mesh;
@@ -4379,7 +3908,9 @@ SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
 
 void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tolerance,
                                               SMESH::array_of_long_array_out GroupsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   ::SMESH_MeshEditor::TListOfListOfNodes aListOfListOfNodes;
@@ -4399,16 +3930,21 @@ void SMESH_MeshEditor_i::FindCoincidentNodes (CORBA::Double                  Tol
   }
   TPythonDump() << "coincident_nodes = " << this << ".FindCoincidentNodes( "
                 << Tolerance << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
 //function : FindCoincidentNodesOnPart
 //purpose  :
 //=======================================================================
+
 void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      theObject,
                                                    CORBA::Double                  Tolerance,
                                                    SMESH::array_of_long_array_out GroupsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TIDSortedNodeSet nodes;
@@ -4433,6 +3969,8 @@ void SMESH_MeshEditor_i::FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr
   TPythonDump() << "coincident_nodes_on_part = " << this << ".FindCoincidentNodesOnPart( "
                 <<theObject<<", "
                 << Tolerance << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //================================================================================
@@ -4447,7 +3985,9 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
                              CORBA::Double                  theTolerance,
                              SMESH::array_of_long_array_out theGroupsOfNodes,
                              const SMESH::ListOfIDSources&  theExceptSubMeshOrGroups)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TIDSortedNodeSet nodes;
@@ -4481,6 +4021,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
                 << theObject<<", "
                 << theTolerance << ", "
                 << theExceptSubMeshOrGroups << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -4489,7 +4031,9 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -4518,17 +4062,22 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
   getEditor().MergeNodes( aListOfListOfNodes );
 
   aTPythonDump <<  "])";
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+
+  declareMeshModified( /*isReComputeSafe=*/false );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
 //function : FindEqualElements
 //purpose  :
 //=======================================================================
+
 void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObject,
                                            SMESH::array_of_long_array_out GroupsOfElementsID)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESH::SMESH_GroupBase_var group = SMESH::SMESH_GroupBase::_narrow(theObject);
@@ -4558,6 +4107,8 @@ void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObj
     TPythonDump() << "equal_elements = " << this << ".FindEqualElements( "
                   <<theObject<<" )";
   }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -4566,7 +4117,9 @@ void SMESH_MeshEditor_i::FindEqualElements(SMESH::SMESH_IDSource_ptr      theObj
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsOfElementsID)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   TPythonDump aTPythonDump;
@@ -4589,10 +4142,12 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO
   }
 
   getEditor().MergeElements(aListOfListOfElementsID);
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+
+  declareMeshModified( /*isReComputeSafe=*/true );
 
   aTPythonDump << "] )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -4601,14 +4156,18 @@ void SMESH_MeshEditor_i::MergeElements(const SMESH::array_of_long_array& GroupsO
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeEqualElements()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   getEditor().MergeEqualElements();
 
-  myMesh->GetMeshDS()->Modified();
+  declareMeshModified( /*isReComputeSafe=*/true );
 
   TPythonDump() << this << ".MergeEqualElements()";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -4621,7 +4180,9 @@ CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
                                             CORBA::Double x,
                                             CORBA::Double y,
                                             CORBA::Double z)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData(/*deleteSearchers=*/false);
 
   const SMDS_MeshNode * node = getMeshDS()->FindNode( NodeID );
@@ -4659,10 +4220,11 @@ CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
     // Update Python script
     TPythonDump() << "isDone = " << this << ".MoveNode( "
                   << NodeID << ", " << TVar(x) << ", " << TVar(y) << ", " << TVar(z) << " )";
-    myMesh->GetMeshDS()->Modified();
-    myMesh->SetIsModified( true );
+    declareMeshModified( /*isReComputeSafe=*/false );
   }
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return true;
 }
 
@@ -4675,16 +4237,19 @@ CORBA::Boolean SMESH_MeshEditor_i::MoveNode(CORBA::Long   NodeID,
 CORBA::Long SMESH_MeshEditor_i::FindNodeClosestTo(CORBA::Double x,
                                                   CORBA::Double y,
                                                   CORBA::Double z)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
 
   if ( !theNodeSearcher ) {
-    theNodeSearcher = myEditor.GetNodeSearcher();
+    theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
   }
   gp_Pnt p( x,y,z );
   if ( const SMDS_MeshNode* node = theNodeSearcher->FindClosestTo( p ))
     return node->GetID();
 
+  SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
 
@@ -4699,7 +4264,9 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
                                                        CORBA::Double y,
                                                        CORBA::Double z,
                                                        CORBA::Long   theNodeID)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   // We keep theNodeSearcher until any mesh modification:
   // 1) initData() deletes theNodeSearcher at any edition,
   // 2) TSearchersDeleter - at any mesh compute event and mesh change
@@ -4713,7 +4280,7 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
   if ( !node ) // preview moving node
   {
     if ( !theNodeSearcher ) {
-      theNodeSearcher = myEditor.GetNodeSearcher();
+      theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
     }
     gp_Pnt p( x,y,z );
     node = theNodeSearcher->FindClosestTo( p );
@@ -4754,11 +4321,13 @@ CORBA::Long SMESH_MeshEditor_i::MoveClosestNodeToPoint(CORBA::Double x,
                   << ".MoveClosestNodeToPoint( "<< x << ", " << y << ", " << z
                   << ", " << nodeID << " )";
 
-    myMesh->GetMeshDS()->Modified();
-    myMesh->SetIsModified( true );
+    declareMeshModified( /*isReComputeSafe=*/false );
   }
 
   return nodeID;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4773,13 +4342,15 @@ SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
                                                            CORBA::Double      y,
                                                            CORBA::Double      z,
                                                            SMESH::ElementType type)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::long_array_var res = new SMESH::long_array;
   vector< const SMDS_MeshElement* > foundElems;
 
   theSearchersDeleter.Set( myMesh );
   if ( !theElementSearcher ) {
-    theElementSearcher = myEditor.GetElementSearcher();
+    theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
   }
   theElementSearcher->FindElementsByPoint( gp_Pnt( x,y,z ),
                                            SMDSAbs_ElementType( type ),
@@ -4788,14 +4359,10 @@ SMESH::long_array* SMESH_MeshEditor_i::FindElementsByPoint(CORBA::Double      x,
   for ( int i = 0; i < foundElems.size(); ++i )
     res[i] = foundElems[i]->GetID();
 
-  if ( !myIsPreviewMode ) // call from tui
-    TPythonDump() << "res = " << this << ".FindElementsByPoint( "
-                  << x << ", "
-                  << y << ", "
-                  << z << ", "
-                  << type << " )";
-
   return res._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4811,7 +4378,9 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
                                              CORBA::Double             y,
                                              CORBA::Double             z,
                                              SMESH::ElementType        type)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::long_array_var res = new SMESH::long_array;
   
   SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
@@ -4839,7 +4408,7 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
     SMDS_ElemIteratorPtr elemsIt( new TIter( elements.begin(), elements.end() ));
 
-    theElementSearcher = myEditor.GetElementSearcher(elemsIt);
+    theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemsIt );
   }
 
   vector< const SMDS_MeshElement* > foundElems;
@@ -4851,17 +4420,12 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
   for ( int i = 0; i < foundElems.size(); ++i )
     res[i] = foundElems[i]->GetID();
 
-  if ( !myIsPreviewMode ) // call from tui
-    TPythonDump() << "res = " << this << ".FindAmongElementsByPoint( "
-                  << elementIDs << ", "
-                  << x << ", "
-                  << y << ", "
-                  << z << ", "
-                  << type << " )";
-
   return res._retn();
-  
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
+
 //=======================================================================
 //function : GetPointState
 //purpose  : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
@@ -4871,12 +4435,17 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
 CORBA::Short SMESH_MeshEditor_i::GetPointState(CORBA::Double x,
                                                CORBA::Double y,
                                                CORBA::Double z)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   theSearchersDeleter.Set( myMesh );
   if ( !theElementSearcher ) {
-    theElementSearcher = myEditor.GetElementSearcher();
+    theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
   }
   return CORBA::Short( theElementSearcher->GetPointState( gp_Pnt( x,y,z )));
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
@@ -4917,7 +4486,9 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
                                    CORBA::Long LastNodeID2,
                                    CORBA::Boolean CreatePolygons,
                                    CORBA::Boolean CreatePolyedrs)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -4960,10 +4531,11 @@ SMESH_MeshEditor_i::SewFreeBorders(CORBA::Long FirstNodeID1,
                                        CreatePolyedrs) );
 
 
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
-
+  declareMeshModified( /*isReComputeSafe=*/false );
   return error;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return SMESH::SMESH_MeshEditor::Sew_Error(0);
 }
 
 
@@ -4978,7 +4550,9 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
                                           CORBA::Long LastNodeID1,
                                           CORBA::Long FirstNodeID2,
                                           CORBA::Long SecondNodeID2)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -5015,11 +4589,11 @@ SMESH_MeshEditor_i::SewConformFreeBorders(CORBA::Long FirstNodeID1,
                                        true,
                                        false, false) );
 
-
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
-
+  declareMeshModified( /*isReComputeSafe=*/false );
   return error;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return SMESH::SMESH_MeshEditor::Sew_Error(0);
 }
 
 
@@ -5036,7 +4610,9 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
                                     CORBA::Long LastNodeIDOnSide,
                                     CORBA::Boolean CreatePolygons,
                                     CORBA::Boolean CreatePolyedrs)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -5076,11 +4652,11 @@ SMESH_MeshEditor_i::SewBorderToSide(CORBA::Long FirstNodeIDOnFreeBorder,
                                        CreatePolygons,
                                        CreatePolyedrs) );
 
-
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
-
+  declareMeshModified( /*isReComputeSafe=*/false );
   return error;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return SMESH::SMESH_MeshEditor::Sew_Error(0);
 }
 
 
@@ -5096,7 +4672,9 @@ SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
                                     CORBA::Long NodeID1OfSide2ToMerge,
                                     CORBA::Long NodeID2OfSide1ToMerge,
                                     CORBA::Long NodeID2OfSide2ToMerge)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   SMESHDS_Mesh* aMesh = getMeshDS();
@@ -5132,11 +4710,11 @@ SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
                                          aSecondNode1ToMerge,
                                          aSecondNode2ToMerge));
 
-
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
-
+  declareMeshModified( /*isReComputeSafe=*/false );
   return error;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return SMESH::SMESH_MeshEditor::Sew_Error(0);
 }
 
 //================================================================================
@@ -5150,7 +4728,9 @@ SMESH_MeshEditor_i::SewSideElements(const SMESH::long_array& IDsOfSide1Elements,
 
 CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
                                                    const SMESH::long_array& newIDs)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   const SMDS_MeshElement* elem = getMeshDS()->FindElement(ide);
@@ -5173,24 +4753,45 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
   MESSAGE("ChangeElementNodes");
   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
 
-  myMesh->GetMeshDS()->Modified();
-  if ( res )
-    myMesh->SetIsModified( true );
+  declareMeshModified( /*isReComputeSafe=*/ !res );
 
   return res;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //=======================================================================
-//function : ConvertToQuadratic
-//purpose  :
+/*!
+ * \brief Makes a part of the mesh quadratic or bi-quadratic
+ */
 //=======================================================================
 
-void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
+void SMESH_MeshEditor_i::convertToQuadratic(CORBA::Boolean            theForce3d,
+                                            CORBA::Boolean            theToBiQuad,
+                                            SMESH::SMESH_IDSource_ptr theObject)
+  throw (SALOME::SALOME_Exception)
 {
-  getEditor().ConvertToQuadratic(theForce3d);
-  TPythonDump() << this << ".ConvertToQuadratic( " << theForce3d << " )";
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+  SMESH_TRY;
+  TIDSortedElemSet elems;
+  bool elemsOK;
+  if ( !( elemsOK = CORBA::is_nil( theObject )))
+  {
+    elemsOK =  idSourceToSet( theObject, getMeshDS(), elems,
+                              SMDSAbs_All, /*emptyIfIsMesh=*/true );
+  }
+  if ( elemsOK )
+  {
+    if ( !elems.empty() && (*elems.begin())->GetType() == SMDSAbs_Node )
+      THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
+
+    if ( elems.empty() ) getEditor().ConvertToQuadratic(theForce3d, theToBiQuad);
+    else                 getEditor().ConvertToQuadratic(theForce3d, elems, theToBiQuad);
+
+    declareMeshModified( /*isReComputeSafe=*/false );
+  }
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -5199,14 +4800,26 @@ void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
 //=======================================================================
 
 CORBA::Boolean SMESH_MeshEditor_i::ConvertFromQuadratic()
+  throw (SALOME::SALOME_Exception)
 {
   CORBA::Boolean isDone = getEditor().ConvertFromQuadratic();
   TPythonDump() << this << ".ConvertFromQuadratic()";
-  myMesh->GetMeshDS()->Modified();
-  if ( isDone )
-    myMesh->SetIsModified( true );
+  declareMeshModified( /*isReComputeSafe=*/!isDone );
   return isDone;
 }
+
+//=======================================================================
+//function : ConvertToQuadratic
+//purpose  :
+//=======================================================================
+
+void SMESH_MeshEditor_i::ConvertToQuadratic(CORBA::Boolean theForce3d)
+  throw (SALOME::SALOME_Exception)
+{
+  convertToQuadratic( theForce3d, false );
+  TPythonDump() << this << ".ConvertToQuadratic("<<theForce3d<<")";
+}
+
 //================================================================================
 /*!
  * \brief Makes a part of the mesh quadratic
@@ -5217,28 +4830,22 @@ void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theF
                                                   SMESH::SMESH_IDSource_ptr theObject)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-  TPythonDump pyDump;
-  TIDSortedElemSet elems;
-  if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
-  {
-    if ( elems.empty() )
-    {
-      ConvertToQuadratic( theForce3d );
-    }
-    else if ( (*elems.begin())->GetType() == SMDSAbs_Node )
-    {
-      THROW_SALOME_CORBA_EXCEPTION("Group of nodes is not allowed", SALOME::BAD_PARAM);
-    }
-    else
-    {
-      getEditor().ConvertToQuadratic(theForce3d, elems);
-    }
-  }
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+  convertToQuadratic( theForce3d, false, theObject );
+  TPythonDump() << this << ".ConvertToQuadraticObject("<<theForce3d<<", "<<theObject<<")";
+}
+
+//================================================================================
+/*!
+ * \brief Makes a part of the mesh bi-quadratic
+ */
+//================================================================================
 
-  pyDump << this << ".ConvertToQuadraticObject( "<<theForce3d<<", "<<theObject<<" )";
+void SMESH_MeshEditor_i::ConvertToBiQuadratic(CORBA::Boolean            theForce3d,
+                                              SMESH::SMESH_IDSource_ptr theObject)
+  throw (SALOME::SALOME_Exception)
+{
+  convertToQuadratic( theForce3d, true, theObject );
+  TPythonDump() << this << ".ConvertToBiQuadratic("<<theForce3d<<", "<<theObject<<")";
 }
 
 //================================================================================
@@ -5250,8 +4857,10 @@ void SMESH_MeshEditor_i::ConvertToQuadraticObject(CORBA::Boolean            theF
 void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr theObject)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
+  SMESH_TRY;
+
   TPythonDump pyDump;
+
   TIDSortedElemSet elems;
   if ( idSourceToSet( theObject, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true ))
   {
@@ -5268,10 +4877,11 @@ void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr th
       getEditor().ConvertFromQuadratic(elems);
     }
   }
-  myMesh->GetMeshDS()->Modified();
-  myMesh->SetIsModified( true );
+  declareMeshModified( /*isReComputeSafe=*/false );
 
   pyDump << this << ".ConvertFromQuadraticObject( "<<theObject<<" )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=======================================================================
@@ -5281,10 +4891,10 @@ void SMESH_MeshEditor_i::ConvertFromQuadraticObject(SMESH::SMESH_IDSource_ptr th
 
 SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
 {
-  SMESH_Gen_i* gen = SMESH_Gen_i::GetSMESHGen();
-  SMESH::SMESH_Mesh_var mesh = gen->CreateEmptyMesh();
-  SALOMEDS::Study_var study = gen->GetCurrentStudy();
-  SALOMEDS::SObject_var meshSO = gen->ObjectToSObject( study, mesh );
+  SMESH_Gen_i*              gen = SMESH_Gen_i::GetSMESHGen();
+  SMESH::SMESH_Mesh_var    mesh = gen->CreateEmptyMesh();
+  SALOMEDS::Study_var     study = gen->GetCurrentStudy();
+  SALOMEDS::SObject_wrap meshSO = gen->ObjectToSObject( study, mesh );
   gen->SetName( meshSO, theMeshName, "Mesh" );
   gen->SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
 
@@ -5292,48 +4902,194 @@ SMESH::SMESH_Mesh_ptr SMESH_MeshEditor_i::makeMesh(const char* theMeshName)
 }
 
 //=======================================================================
-//function : DumpGroupsList
+//function : dumpGroupsList
 //purpose  :
 //=======================================================================
-void SMESH_MeshEditor_i::DumpGroupsList(TPythonDump &               theDumpPython,
+
+void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPython,
                                         const SMESH::ListOfGroups * theGroupList)
 {
-  bool isDumpGroupList = theGroupList && theGroupList->length() > 0;
-  if(isDumpGroupList) {
+  bool isDumpGroupList = ( theGroupList && theGroupList->length() > 0 );
+  if ( isDumpGroupList )
     theDumpPython << theGroupList << " = ";
+}
+
+//================================================================================
+/*!
+  \brief Generates the unique group name.
+  \param thePrefix name prefix
+  \return unique name
+*/
+//================================================================================
+
+string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
+{
+  SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
+  set<string> groupNames;
+
+  // Get existing group names
+  for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
+    SMESH::SMESH_GroupBase_var aGroup = groups[i];
+    if (CORBA::is_nil(aGroup))
+      continue;
+
+    CORBA::String_var name = aGroup->GetName();
+    groupNames.insert( name.in() );
+  }
+
+  // Find new name
+  string name = thePrefix;
+  int index = 0;
+
+  while (!groupNames.insert(name).second)
+    name = SMESH_Comment( thePrefix ) << "_" << index++;
+
+  return name;
+}
+
+//================================================================================
+/*!
+ * \brief Prepare SMESH_IDSource for work
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::prepareIdSource(SMESH::SMESH_IDSource_ptr theObject)
+{
+  if ( SMESH::Filter_i* filter = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
+  {
+    SMESH::SMESH_Mesh_var mesh = myMesh_i->_this();
+    filter->SetMesh( mesh );
+  }
+}
+//================================================================================
+/*!
+ * \brief Retrieve elements of given type from SMESH_IDSource
+ */
+//================================================================================
+
+bool SMESH_MeshEditor_i::idSourceToSet(SMESH::SMESH_IDSource_ptr  theIDSource,
+                                       const SMESHDS_Mesh*        theMeshDS,
+                                       TIDSortedElemSet&          theElemSet,
+                                       const SMDSAbs_ElementType  theType,
+                                       const bool                 emptyIfIsMesh,
+                                       IDSource_Error*            error)
+
+{
+  if ( error ) *error = IDSource_OK;
+
+  if ( CORBA::is_nil( theIDSource ) )
+  {
+    if ( error ) *error = IDSource_INVALID;
+    return false;
+  }
+  if ( emptyIfIsMesh && SMESH::DownCast<SMESH_Mesh_i*>( theIDSource ))
+  {
+    if ( error && getMeshDS()->GetMeshInfo().NbElements( theType ) == 0 )
+      *error = IDSource_EMPTY;
+    return true;
+  }
+  prepareIdSource( theIDSource );
+  SMESH::long_array_var anIDs = theIDSource->GetIDs();
+  if ( anIDs->length() == 0 )
+  {
+    if ( error ) *error = IDSource_EMPTY;
+    return false;
+  }
+  SMESH::array_of_ElementType_var types = theIDSource->GetTypes();
+  if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
+  {
+    if ( theType == SMDSAbs_All || theType == SMDSAbs_Node )
+    {
+      arrayToSet( anIDs, getMeshDS(), theElemSet, SMDSAbs_Node );
+    }
+    else
+    {
+      if ( error ) *error = IDSource_INVALID;
+      return false;
+    }
+  }
+  else
+  {
+    arrayToSet( anIDs, getMeshDS(), theElemSet, theType);
+    if ( bool(anIDs->length()) != bool(theElemSet.size()))
+    {
+      if ( error ) *error = IDSource_INVALID;
+      return false;
+    }
   }
+  return true;
 }
 
 //================================================================================
 /*!
-  \brief Generates the unique group name.
-  \param thePrefix name prefix
-  \return unique name
-*/
+ * \brief Duplicates given elements, i.e. creates new elements based on the
+ *        same nodes as the given ones.
+ * \param theElements - container of elements to duplicate.
+ * \param theGroupName - a name of group to contain the generated elements.
+ *                    If a group with such a name already exists, the new elements
+ *                    are added to the existng group, else a new group is created.
+ *                    If \a theGroupName is empty, new elements are not added 
+ *                    in any group.
+ * \return a group where the new elements are added. NULL if theGroupName == "".
+ * \sa DoubleNode()
+ */
 //================================================================================
-string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
+
+SMESH::SMESH_Group_ptr
+SMESH_MeshEditor_i::DoubleElements(SMESH::SMESH_IDSource_ptr theElements,
+                                   const char*               theGroupName)
+  throw (SALOME::SALOME_Exception)
 {
-  SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
-  set<string> groupNames;
+  SMESH::SMESH_Group_var newGroup;
 
-  // Get existing group names
-  for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
-    SMESH::SMESH_GroupBase_var aGroup = groups[i];
-    if (CORBA::is_nil(aGroup))
-      continue;
+  SMESH_TRY;
+  initData();
 
-    CORBA::String_var name = aGroup->GetName();
-    groupNames.insert( name.in() );
-  }
+  TPythonDump pyDump;
 
-  // Find new name
-  string name = thePrefix;
-  int index = 0;
+  TIDSortedElemSet elems;
+  if ( idSourceToSet( theElements, getMeshDS(), elems, SMDSAbs_All, /*emptyIfIsMesh=*/true))
+  {
+    getEditor().DoubleElements( elems );
 
-  while (!groupNames.insert(name).second)
-    name = SMESH_Comment( thePrefix ) << "_" << index;
+    if ( strlen( theGroupName ) && !getEditor().GetLastCreatedElems().IsEmpty() )
+    {
+      // group type
+      SMESH::ElementType type =
+        SMESH::ElementType( getEditor().GetLastCreatedElems().Value(1)->GetType() );
+      // find existing group
+      SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
+      for ( size_t i = 0; i < groups->length(); ++i )
+        if ( groups[i]->GetType() == type )
+        {
+          CORBA::String_var name = groups[i]->GetName();
+          if ( strcmp( name, theGroupName ) == 0 ) {
+            newGroup = SMESH::SMESH_Group::_narrow( groups[i] );
+            break;
+          }
+        }
+      // create a new group
+      if ( newGroup->_is_nil() )
+        newGroup = myMesh_i->CreateGroup( type, theGroupName );
+      // fill newGroup
+      if ( SMESH_Group_i* group_i = SMESH::DownCast< SMESH_Group_i* >( newGroup ))
+      {
+        SMESHDS_Group* groupDS = static_cast< SMESHDS_Group* >( group_i->GetGroupDS() );
+        const SMESH_SequenceOfElemPtr& aSeq = getEditor().GetLastCreatedElems();
+        for ( int i = 1; i <= aSeq.Length(); i++ )
+          groupDS->SMDSGroup().Add( aSeq(i) );
+      }
+    }
+  }
+  // python dump
+  if ( !newGroup->_is_nil() )
+    pyDump << newGroup << " = ";
+  pyDump << this << ".DoubleElements( "
+         << theElements << ", " << "'" << theGroupName <<"')";
 
-  return name;
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return newGroup._retn();
 }
 
 //================================================================================
@@ -5350,7 +5106,9 @@ string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
 
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNodes,
                                                 const SMESH::long_array& theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   list< int > aListOfNodes;
@@ -5364,14 +5122,15 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNode
 
   bool aResult = getEditor().DoubleNodes( aListOfNodes, aListOfElems );
 
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
 
   // Update Python script
   TPythonDump() << this << ".DoubleNodes( " << theNodes << ", "<< theModifiedElems << " )";
 
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5387,7 +5146,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodes( const SMESH::long_array& theNode
 
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeId,
                                                const SMESH::long_array& theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::long_array_var aNodes = new SMESH::long_array;
   aNodes->length( 1 );
   aNodes[ 0 ] = theNodeId;
@@ -5399,6 +5160,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeI
   pyDump << this << ".DoubleNode( " << theNodeId << ", " << theModifiedElems << " )";
 
   return done;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5414,7 +5178,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNode( CORBA::Long              theNodeI
 
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr theNodes,
                                                    SMESH::SMESH_GroupBase_ptr theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
     return false;
 
@@ -5435,8 +5201,12 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr th
   pyDump << this << ".DoubleNodeGroup( " << theNodes << ", " << theModifiedElems << " )";
 
   return done;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
+//================================================================================
 /*!
  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements.
  * Works as DoubleNodeGroup(), but returns a new group with newly created nodes.
@@ -5445,10 +5215,14 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroup(SMESH::SMESH_GroupBase_ptr th
  * \return a new group with newly created nodes
  * \sa DoubleNodeGroup()
  */
+//================================================================================
+
 SMESH::SMESH_Group_ptr
 SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
                                         SMESH::SMESH_GroupBase_ptr theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::SMESH_Group_var aNewGroup;
 
   if ( CORBA::is_nil( theNodes ) && theNodes->GetType() != SMESH::NODE )
@@ -5484,6 +5258,9 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
          << theModifiedElems << " )";
 
   return aNewGroup._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5499,10 +5276,11 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
 
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& theNodes,
                                                     const SMESH::ListOfGroups& theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-
   std::list< int > aNodes;
   int i, n, j, m;
   for ( i = 0, n = theNodes.length(); i < n; i++ )
@@ -5530,15 +5308,14 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& t
 
   bool aResult = getEditor().DoubleNodes( aNodes, anElems );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
+  declareMeshModified( /*isReComputeSafe=*/false );
 
   TPythonDump() << this << ".DoubleNodeGroups( " << theNodes << ", " << theModifiedElems << " )";
 
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5555,6 +5332,7 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeGroups(const SMESH::ListOfGroups& t
 SMESH::SMESH_Group_ptr
 SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
                                          const SMESH::ListOfGroups& theModifiedElems )
+  throw (SALOME::SALOME_Exception)
 {
   SMESH::SMESH_Group_var aNewGroup;
 
@@ -5598,11 +5376,11 @@ SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theElems,
                                                    const SMESH::long_array& theNodesNot,
                                                    const SMESH::long_array& theAffectedElems )
-
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-
   SMESHDS_Mesh* aMeshDS = getMeshDS();
   TIDSortedElemSet anElems, aNodes, anAffected;
   arrayToSet(theElems, aMeshDS, anElems, SMDSAbs_All);
@@ -5611,15 +5389,15 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theE
 
   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
   // Update Python script
   TPythonDump() << this << ".DoubleNodeElem( " << theElems << ", "
                 << theNodesNot << ", " << theAffectedElems << " )";
+
+  declareMeshModified( /*isReComputeSafe=*/false );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5639,8 +5417,9 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElem( const SMESH::long_array& theE
 CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_array& theElems,
                                                             const SMESH::long_array& theNodesNot,
                                                             GEOM::GEOM_Object_ptr    theShape )
-
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
 
@@ -5652,15 +5431,15 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_ar
   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodeElemInRegion( " << theElems << ", "
                 << theNodesNot << ", " << theShape << " )";
+
+  declareMeshModified( /*isReComputeSafe=*/false );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5675,10 +5454,13 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemInRegion ( const SMESH::long_ar
 */
 //================================================================================
 
-CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
-                                                       SMESH::SMESH_GroupBase_ptr theNodesNot,
-                                                       SMESH::SMESH_GroupBase_ptr theAffectedElems)
+CORBA::Boolean
+SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_ptr theElems,
+                                        SMESH::SMESH_GroupBase_ptr theNodesNot,
+                                        SMESH::SMESH_GroupBase_ptr theAffectedElems)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
     return false;
 
@@ -5693,17 +5475,18 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_pt
 
   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroup( " << theElems << ", "
                 << theNodesNot << ", " << theAffectedElems << " )";
+
+  declareMeshModified( /*isReComputeSafe=*/false );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
+//================================================================================
 /*!
  * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
  * Works as DoubleNodeElemGroup(), but returns a new group with newly created elements.
@@ -5714,10 +5497,13 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroup(SMESH::SMESH_GroupBase_pt
  * \return a new group with newly created elements
  * \sa DoubleNodeElemGroup()
  */
+//================================================================================
+
 SMESH::SMESH_Group_ptr
 SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
                                            SMESH::SMESH_GroupBase_ptr theNodesNot,
                                            SMESH::SMESH_GroupBase_ptr theAffectedElems)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump pyDump;
   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroup2New( theElems,
@@ -5735,13 +5521,28 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupNew(SMESH::SMESH_GroupBase_ptr theElems,
   return elemGroup._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
+ * Works as DoubleNodeElemGroup(), but returns a new group with newly created 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 a new group with newly created elements
+ * \sa DoubleNodeElemGroup()
+ */
+//================================================================================
+
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
                                             SMESH::SMESH_GroupBase_ptr theNodesNot,
                                             SMESH::SMESH_GroupBase_ptr theAffectedElems,
                                             CORBA::Boolean             theElemGroupNeeded,
                                             CORBA::Boolean             theNodeGroupNeeded)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
   aTwoGroups->length( 2 );
@@ -5761,14 +5562,12 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
 
   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
 
-  myMesh->GetMeshDS()->Modified();
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
 
   TPythonDump pyDump;
 
   if ( aResult )
   {
-    myMesh->SetIsModified( true );
-
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems->GetName();
     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
@@ -5804,6 +5603,9 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
   aTwoGroups[0] = aNewElemGroup._retn();
   aTwoGroups[1] = aNewNodeGroup._retn();
   return aTwoGroups._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5819,11 +5621,13 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
 */
 //================================================================================
 
-CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
-                                                               SMESH::SMESH_GroupBase_ptr theNodesNot,
-                                                               GEOM::GEOM_Object_ptr      theShape )
-
+CORBA::Boolean
+SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_GroupBase_ptr theElems,
+                                                SMESH::SMESH_GroupBase_ptr theNodesNot,
+                                                GEOM::GEOM_Object_ptr      theShape )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   if ( CORBA::is_nil( theElems ) && theElems->GetType() == SMESH::NODE )
     return false;
 
@@ -5839,27 +5643,25 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroupInRegion(SMESH::SMESH_Grou
   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
 
 
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupInRegion( " << theElems << ", "
                 << theNodesNot << ", " << theShape << " )";
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
 /*!
-  \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(), DoubleNodeElemGroupsNew()
-*/
+ * \brief Re-load elements from a list of groups into a TIDSortedElemSet
+ *  \param [in] theGrpList - groups
+ *  \param [in] theMeshDS -  mesh
+ *  \param [out] theElemSet - set of elements
+ *  \param [in] theIsNodeGrp - is \a theGrpList includes goups of nodes
+ */
 //================================================================================
 
 static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
@@ -5879,10 +5681,26 @@ static void listOfGroupToSet(const SMESH::ListOfGroups& theGrpList,
   }
 }
 
-CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
-                                                        const SMESH::ListOfGroups& theNodesNot,
-                                                        const SMESH::ListOfGroups& theAffectedElems)
+//================================================================================
+/*!
+  \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(), DoubleNodeElemGroupsNew()
+*/
+//================================================================================
+
+CORBA::Boolean
+SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroups& theElems,
+                                         const SMESH::ListOfGroups& theNodesNot,
+                                         const SMESH::ListOfGroups& theAffectedElems)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
 
@@ -5894,15 +5712,15 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodeElemGroups(const SMESH::ListOfGroup
 
   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroups( " << &theElems << ", "
                 << &theNodesNot << ", " << &theAffectedElems << " )";
+
+  declareMeshModified( /*isReComputeSafe=*/false );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -5922,6 +5740,7 @@ SMESH::SMESH_Group_ptr
 SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
                                             const SMESH::ListOfGroups& theNodesNot,
                                             const SMESH::ListOfGroups& theAffectedElems)
+  throw (SALOME::SALOME_Exception)
 {
   TPythonDump pyDump;
   SMESH::ListOfGroups_var twoGroups = DoubleNodeElemGroups2New( theElems,
@@ -5939,13 +5758,28 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupsNew(const SMESH::ListOfGroups& theElems,
   return elemGroup._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Creates a hole in a mesh by doubling the nodes of some particular elements
+ * Works as DoubleNodeElemGroups(), but returns a new group with newly created elements.
+  \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 a new group with newly created elements
+ * \sa DoubleNodeElemGroups()
+ */
+//================================================================================
+
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems,
                                              const SMESH::ListOfGroups& theNodesNot,
                                              const SMESH::ListOfGroups& theAffectedElems,
                                              CORBA::Boolean             theElemGroupNeeded,
                                              CORBA::Boolean             theNodeGroupNeeded)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   SMESH::SMESH_Group_var aNewElemGroup, aNewNodeGroup;
   SMESH::ListOfGroups_var aTwoGroups = new SMESH::ListOfGroups();
   aTwoGroups->length( 2 );
@@ -5961,13 +5795,11 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems
 
   bool aResult = getEditor().DoubleNodes( anElems, aNodes, anAffected );
 
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
 
-  myMesh->GetMeshDS()->Modified();
   TPythonDump pyDump;
   if ( aResult )
   {
-    myMesh->SetIsModified( true );
-
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems[0]->GetName();
     string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
@@ -6003,6 +5835,9 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems
   aTwoGroups[0] = aNewElemGroup._retn();
   aTwoGroups[1] = aNewNodeGroup._retn();
   return aTwoGroups._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -6023,7 +5858,9 @@ CORBA::Boolean
 SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theElems,
                                                  const SMESH::ListOfGroups& theNodesNot,
                                                  GEOM::GEOM_Object_ptr      theShape )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
 
@@ -6035,20 +5872,21 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theE
   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
   bool aResult = getEditor().DoubleNodesInRegion( anElems, aNodes, aShape );
 
-
-  myMesh->GetMeshDS()->Modified();
-  if ( aResult )
-    myMesh->SetIsModified( true );
-
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodeElemGroupsInRegion( " << &theElems << ", "
                 << &theNodesNot << ", " << theShape << " )";
+
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
 /*!
-  \brief Identify the elements that will be affected by node duplication (actual duplication is not performed.
+  \brief Identify the elements that will be affected by node duplication (actual
+         duplication is not performed.
   This method is the first step of DoubleNodeElemGroupsInRegion.
   \param theElems - list of groups of elements (edges or faces) to be replicated
   \param theNodesNot - list of groups of nodes not to replicated
@@ -6057,13 +5895,15 @@ SMESH_MeshEditor_i::DoubleNodeElemGroupsInRegion(const SMESH::ListOfGroups& theE
          The replicated nodes should be associated to affected elements.
   \return groups of affected elements
   \sa DoubleNodeElemGroupsInRegion()
- */
+*/
 //================================================================================
 SMESH::ListOfGroups*
 SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theElems,
                                                 const SMESH::ListOfGroups& theNodesNot,
                                                 GEOM::GEOM_Object_ptr      theShape )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   MESSAGE("AffectedElemGroupsInRegion");
   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
   bool isEdgeGroup = false;
@@ -6087,80 +5927,74 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   bool aResult = aMeshEditor.AffectedElemGroupsInRegion(anElems, aNodes, aShape, anAffected);
 
 
-  myMesh->GetMeshDS()->Modified();
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
+
   TPythonDump pyDump;
   if (aResult)
+  {
+    int lg = anAffected.size();
+    MESSAGE("lg="<< lg);
+    SMESH::long_array_var volumeIds = new SMESH::long_array;
+    volumeIds->length(lg);
+    SMESH::long_array_var faceIds = new SMESH::long_array;
+    faceIds->length(lg);
+    SMESH::long_array_var edgeIds = new SMESH::long_array;
+    edgeIds->length(lg);
+    int ivol = 0;
+    int iface = 0;
+    int iedge = 0;
+
+    TIDSortedElemSet::const_iterator eIt = anAffected.begin();
+    for (; eIt != anAffected.end(); ++eIt)
     {
-      myMesh->SetIsModified(true);
-
-      int lg = anAffected.size();
-      MESSAGE("lg="<< lg);
-      SMESH::long_array_var volumeIds = new SMESH::long_array;
-      volumeIds->length(lg);
-      SMESH::long_array_var faceIds = new SMESH::long_array;
-      faceIds->length(lg);
-      SMESH::long_array_var edgeIds = new SMESH::long_array;
-      edgeIds->length(lg);
-      int ivol = 0;
-      int iface = 0;
-      int iedge = 0;
-
-      TIDSortedElemSet::const_iterator eIt = anAffected.begin();
-      for (; eIt != anAffected.end(); ++eIt)
-        {
-          const SMDS_MeshElement* anElem = *eIt;
-          if (!anElem)
-            continue;
-          int elemId = anElem->GetID();
-          if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
-            volumeIds[ivol++] = elemId;
-          else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
-            faceIds[iface++] = elemId;
-          else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
-            edgeIds[iedge++] = elemId;
-        }
-      volumeIds->length(ivol);
-      faceIds->length(iface);
-      edgeIds->length(iedge);
-
-      aNewVolumeGroup->Add(volumeIds);
-      aNewFaceGroup->Add(faceIds);
-      aNewEdgeGroup->Add(edgeIds);
-      isVolumeGroup = (aNewVolumeGroup->Size() > 0);
-      isFaceGroup = (aNewFaceGroup->Size() > 0);
-      isEdgeGroup = (aNewEdgeGroup->Size() > 0);
+      const SMDS_MeshElement* anElem = *eIt;
+      if (!anElem)
+        continue;
+      int elemId = anElem->GetID();
+      if (myMesh->GetElementType(elemId, true) == SMDSAbs_Volume)
+        volumeIds[ivol++] = elemId;
+      else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Face)
+        faceIds[iface++] = elemId;
+      else if (myMesh->GetElementType(elemId, true) == SMDSAbs_Edge)
+        edgeIds[iedge++] = elemId;
     }
+    volumeIds->length(ivol);
+    faceIds->length(iface);
+    edgeIds->length(iedge);
+
+    aNewVolumeGroup->Add(volumeIds);
+    aNewFaceGroup->Add(faceIds);
+    aNewEdgeGroup->Add(edgeIds);
+    isVolumeGroup = (aNewVolumeGroup->Size() > 0);
+    isFaceGroup = (aNewFaceGroup->Size() > 0);
+    isEdgeGroup = (aNewEdgeGroup->Size() > 0);
+  }
 
   int nbGroups = 0;
-  if (isEdgeGroup)
-    nbGroups++;
-  if (isFaceGroup)
-    nbGroups++;
-  if (isVolumeGroup)
-    nbGroups++;
+  if (isEdgeGroup)   nbGroups++;
+  if (isFaceGroup)   nbGroups++;
+  if (isVolumeGroup) nbGroups++;
   aListOfGroups->length(nbGroups);
 
   int i = 0;
-  if (isEdgeGroup)
-    aListOfGroups[i++] = aNewEdgeGroup._retn();
-  if (isFaceGroup)
-    aListOfGroups[i++] = aNewFaceGroup._retn();
-  if (isVolumeGroup)
-    aListOfGroups[i++] = aNewVolumeGroup._retn();
+  if (isEdgeGroup)   aListOfGroups[i++] = aNewEdgeGroup._retn();
+  if (isFaceGroup)   aListOfGroups[i++] = aNewFaceGroup._retn();
+  if (isVolumeGroup) aListOfGroups[i++] = aNewVolumeGroup._retn();
 
   // Update Python script
 
   pyDump << "[ ";
-  if (isEdgeGroup)
-    pyDump << aNewEdgeGroup << ", ";
-  if (isFaceGroup)
-    pyDump << aNewFaceGroup << ", ";
-  if (isVolumeGroup)
-    pyDump << aNewVolumeGroup << ", ";
+  if (isEdgeGroup)   pyDump << aNewEdgeGroup << ", ";
+  if (isFaceGroup)   pyDump << aNewFaceGroup << ", ";
+  if (isVolumeGroup) pyDump << aNewVolumeGroup << ", ";
   pyDump << "] = ";
-  pyDump << this << ".AffectedElemGroupsInRegion( " << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
+  pyDump << this << ".AffectedElemGroupsInRegion( "
+         << &theElems << ", " << &theNodesNot << ", " << theShape << " )";
 
   return aListOfGroups._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }
 
 //================================================================================
@@ -6172,40 +6006,63 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
 //================================================================================
 
 CORBA::Boolean SMESH_MeshEditor_i::Make2DMeshFrom3D()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   bool aResult = getEditor().Make2DMeshFrom3D();
-  myMesh->GetMeshDS()->Modified();
+
   TPythonDump() << "isDone = " << this << ".Make2DMeshFrom3D()";
+
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return false;
 }
 
 //================================================================================
 /*!
  * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
- * The list of groups must describe a partition of the mesh volumes.
+ * The list of groups must contain at least two groups. The groups have to be disjoint:
+ * no common element into two different groups.
  * The nodes of the internal faces at the boundaries of the groups are doubled.
- * In option, the internal faces are replaced by flat elements.
- * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * Optionally, the internal faces are replaced by flat elements.
+ * Triangles are transformed into prisms, and quadrangles into hexahedrons.
  * The flat elements are stored in groups of volumes.
- * @param theDomains - list of groups of volumes
- * @param createJointElems - if TRUE, create the elements
- * @return TRUE if operation has been completed successfully, FALSE otherwise
+ * These groups are named according to the position of the group in the list:
+ * the group j_n_p is the group of the flat elements that are built between the group #n and the group #p in the list.
+ * If there is no shared faces between the group #n and the group #p in the list, the group j_n_p is not created.
+ * All the flat elements are gathered into the group named "joints3D" (or "joints2D" in 2D situation).
+ * The flat element of the multiple junctions between the simple junction are stored in a group named "jointsMultiples".
+ * \param theDomains - list of groups of volumes
+ * \param createJointElems - if TRUE, create the elements
+ * \param onAllBoundaries - if TRUE, the nodes and elements are also created on
+ *        the boundary between \a theDomains and the rest mesh
+ * \return TRUE if operation has been completed successfully, FALSE otherwise
  */
 //================================================================================
 
-CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
-                                                                 CORBA::Boolean createJointElems )
+CORBA::Boolean
+SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
+                                                  CORBA::Boolean             createJointElems,
+                                                  CORBA::Boolean             onAllBoundaries )
   throw (SALOME::SALOME_Exception)
 {
-  initData();
+  bool isOK = false;
 
+  SMESH_TRY;
+  initData();
 
   SMESHDS_Mesh* aMeshDS = getMeshDS();
 
+  // MESSAGE("theDomains.length = "<<theDomains.length());
+  if ( theDomains.length() <= 1 && !onAllBoundaries )
+    THROW_SALOME_CORBA_EXCEPTION("At least 2 groups are required.", SALOME::BAD_PARAM);
+
   vector<TIDSortedElemSet> domains;
-  domains.clear();
+  domains.resize( theDomains.length() );
 
   for ( int i = 0, n = theDomains.length(); i < n; i++ )
   {
@@ -6214,23 +6071,25 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::Li
     {
 //      if ( aGrp->GetType() != SMESH::VOLUME )
 //        THROW_SALOME_CORBA_EXCEPTION("Not a volume group", SALOME::BAD_PARAM);
-      TIDSortedElemSet domain;
-      domain.clear();
-      domains.push_back(domain);
       SMESH::long_array_var anIDs = aGrp->GetIDs();
       arrayToSet( anIDs, aMeshDS, domains[ i ], SMDSAbs_All );
     }
   }
 
-  bool aResult = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems );
+  isOK = getEditor().DoubleNodesOnGroupBoundaries( domains, createJointElems, onAllBoundaries );
   // TODO publish the groups of flat elements in study
 
-  myMesh->GetMeshDS()->Modified();
+  declareMeshModified( /*isReComputeSafe=*/ !isOK );
 
   // Update Python script
   TPythonDump() << "isDone = " << this << ".DoubleNodesOnGroupBoundaries( " << &theDomains
-      << ", " << createJointElems << " )";
-  return aResult;
+                << ", " << createJointElems << ", " << onAllBoundaries << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  myMesh_i->CreateGroupServants(); // publish created groups if any
+
+  return isOK;
 }
 
 //================================================================================
@@ -6245,11 +6104,13 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::Li
  */
 //================================================================================
 
-CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
+CORBA::Boolean
+SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
-
   SMESHDS_Mesh* aMeshDS = getMeshDS();
 
   vector<TIDSortedElemSet> faceGroups;
@@ -6271,59 +6132,75 @@ CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH:
   bool aResult = getEditor().CreateFlatElementsOnFacesGroups( faceGroups );
   // TODO publish the groups of flat elements in study
 
-  myMesh->GetMeshDS()->Modified();
+  declareMeshModified( /*isReComputeSafe=*/ !aResult );
 
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
+  TPythonDump() << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
   return aResult;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return false;
 }
 
+//================================================================================
 /*!
- *  \brief identify all the elements around a geom shape, get the faces delimiting the hole
- *  Build groups of volume to remove, groups of faces to replace on the skin of the object,
- *  groups of faces to remove inside the object, (idem edges).
- *  Build ordered list of nodes at the border of each group of faces to replace (to be used to build a geom subshape)
+ *  \brief Identify all the elements around a geom shape, get the faces delimiting
+ *         the hole.
+ *
+ *  Build groups of volume to remove, groups of faces to replace on the skin of the
+ *  object, groups of faces to remove inside the object, (idem edges).
+ *  Build ordered list of nodes at the border of each group of faces to replace
+ *  (to be used to build a geom subshape).
  */
-void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double radius,
-                                        GEOM::GEOM_Object_ptr theShape,
-                                        const char* groupName,
-                                        const SMESH::double_array& theNodesCoords,
+//================================================================================
+
+void SMESH_MeshEditor_i::CreateHoleSkin(CORBA::Double                  radius,
+                                        GEOM::GEOM_Object_ptr          theShape,
+                                        const char*                    groupName,
+                                        const SMESH::double_array&     theNodesCoords,
                                         SMESH::array_of_long_array_out GroupsOfNodes)
-throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
+
   initData();
   std::vector<std::vector<int> > aListOfListOfNodes;
   ::SMESH_MeshEditor aMeshEditor( myMesh );
 
   theSearchersDeleter.Set( myMesh ); // remove theNodeSearcher if mesh is other
   if ( !theNodeSearcher )
-    theNodeSearcher = aMeshEditor.GetNodeSearcher();
+    theNodeSearcher = SMESH_MeshAlgos::GetNodeSearcher( *getMeshDS() );
 
   vector<double> nodesCoords;
   for (int i = 0; i < theNodesCoords.length(); i++)
-    {
-      nodesCoords.push_back( theNodesCoords[i] );
+  {
+    nodesCoords.push_back( theNodesCoords[i] );
   }
 
   TopoDS_Shape aShape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( theShape );
-  aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName, nodesCoords, aListOfListOfNodes);
+  aMeshEditor.CreateHoleSkin(radius, aShape, theNodeSearcher, groupName,
+                             nodesCoords, aListOfListOfNodes);
 
   GroupsOfNodes = new SMESH::array_of_long_array;
   GroupsOfNodes->length( aListOfListOfNodes.size() );
   std::vector<std::vector<int> >::iterator llIt = aListOfListOfNodes.begin();
   for ( CORBA::Long i = 0; llIt != aListOfListOfNodes.end(); llIt++, i++ )
-    {
-      vector<int>& aListOfNodes = *llIt;
-      vector<int>::iterator lIt = aListOfNodes.begin();;
-      SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
-      aGroup.length( aListOfNodes.size() );
-      for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
-        aGroup[ j ] = (*lIt);
-    }
+  {
+    vector<int>& aListOfNodes = *llIt;
+    vector<int>::iterator lIt = aListOfNodes.begin();;
+    SMESH::long_array& aGroup = (*GroupsOfNodes)[ i ];
+    aGroup.length( aListOfNodes.size() );
+    for ( int j = 0; lIt != aListOfNodes.end(); lIt++, j++ )
+      aGroup[ j ] = (*lIt);
+  }
   TPythonDump() << "lists_nodes = " << this << ".CreateHoleSkin( "
-      << radius << ", " << theShape << ", " << ", " << groupName << ", " << theNodesCoords << " )";
-}
+                << radius << ", "
+                << theShape
+                << ", '" << groupName << "', "
+                << theNodesCoords << " )";
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
 
 // issue 20749 ===================================================================
 /*!
@@ -6350,7 +6227,9 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
                                      CORBA::Boolean            toCopyElements,
                                      CORBA::Boolean            toCopyExistingBondary,
                                      SMESH::SMESH_Group_out    group)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   initData();
 
   if ( dim > SMESH::BND_1DFROM2D )
@@ -6416,6 +6295,9 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
 
   group = group_var._retn();
   return mesh_var._retn();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return SMESH::SMESH_Mesh::_nil();
 }
 
 //================================================================================
@@ -6444,8 +6326,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
                                                      SMESH::SMESH_Group_out group)
   throw (SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-
+  SMESH_TRY;
   initData();
 
   if ( dim > SMESH::BND_1DFROM2D )
@@ -6572,4 +6453,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   mesh  = mesh_var._retn();
   group = group_var._retn();
   return nbAdded;
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return 0;
 }