Salome HOME
Fix regressions of tests
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index c477e729ef5cda7a95eca5fb86238ebf132fea69..d06ce73062e66f972b1c4fb3220c5b04e0fb1362 100644 (file)
@@ -46,8 +46,6 @@
 #include "SMESH_OctreeNode.hxx"
 #include "SMESH_subMesh.hxx"
 
-#include <Basics_OCCTVersion.hxx>
-
 #include "utilities.h"
 #include "chrono.hxx"
 
 #include <sstream>
 
 #include <boost/tuple/tuple.hpp>
+#include <boost/container/flat_set.hpp>
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx>
+#include <OSD_Parallel.hxx>
+
+#include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
 
 using namespace std;
 using namespace SMESH::Controls;
 
-namespace
-{
-  template < class ELEM_SET >
-  SMDS_ElemIteratorPtr elemSetIterator( const ELEM_SET& elements )
-  {
-    typedef SMDS_SetIterator
-      < SMDS_pElement, typename ELEM_SET::const_iterator> TSetIterator;
-    return SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
-  }
-}
-
 //=======================================================================
 //function : SMESH_MeshEditor
 //purpose  :
@@ -145,8 +136,8 @@ SMESHDS_Mesh * SMESH_MeshEditor::GetMeshDS()
 
 void SMESH_MeshEditor::ClearLastCreated()
 {
-  myLastCreatedNodes.Clear();
-  myLastCreatedElems.Clear();
+  SMESHUtils::FreeVector( myLastCreatedElems );
+  SMESHUtils::FreeVector( myLastCreatedNodes );
 }
 
 //================================================================================
@@ -171,7 +162,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn
         myIsQuad = elem->IsQuadratic();
         if ( myType == SMDSAbs_Volume && !basicOnly )
         {
-          vector<int > quant = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+          vector<int> quant = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
           myPolyhedQuantities.swap( quant );
         }
       }
@@ -378,7 +369,7 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
 
   default:;
   }
-  if ( e ) myLastCreatedElems.Append( e );
+  if ( e ) myLastCreatedElems.push_back( e );
   return e;
 }
 
@@ -412,8 +403,7 @@ SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> & nodeIDs,
 int SMESH_MeshEditor::Remove (const list< int >& theIDs,
                               const bool         isNodes )
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   SMESHDS_Mesh* aMesh = GetMeshDS();
   set< SMESH_subMesh *> smmap;
@@ -493,7 +483,7 @@ void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& eleme
   }
   else
   {
-    elemIt = elemSetIterator( elements );
+    elemIt = SMESHUtils::elemSetIterator( elements );
   }
 
   while ( elemIt->more() )
@@ -506,8 +496,8 @@ void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& eleme
       SMDS_ElemIteratorPtr it0D = n->GetInverseElementIterator( SMDSAbs_0DElement );
       if ( duplicateElements || !it0D->more() )
       {
-        myLastCreatedElems.Append( GetMeshDS()->Add0DElement( n ));
-        all0DElems.insert( myLastCreatedElems.Last() );
+        myLastCreatedElems.push_back( GetMeshDS()->Add0DElement( n ));
+        all0DElems.insert( myLastCreatedElems.back() );
       }
       while ( it0D->more() )
         all0DElems.insert( it0D->next() );
@@ -523,8 +513,7 @@ void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& eleme
 
 int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   SMESHDS_Mesh * aMesh = GetMeshDS();
   if ( aMesh->ShapeToMesh().IsNull() )
@@ -691,19 +680,18 @@ static bool getNodesFromTwoTria(const SMDS_MeshElement * theTria1,
 bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
                                     const SMDS_MeshElement * theTria2 )
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
-  if (!theTria1 || !theTria2)
+  if ( !theTria1 || !theTria2 ||
+       !dynamic_cast<const SMDS_MeshCell*>( theTria1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( theTria2 ) ||
+       theTria1->GetType() != SMDSAbs_Face ||
+       theTria2->GetType() != SMDSAbs_Face )
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( theTria1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( theTria2 );
-  if (!F2) return false;
   if ((theTria1->GetEntityType() == SMDSEntity_Triangle) &&
-      (theTria2->GetEntityType() == SMDSEntity_Triangle)) {
-
+      (theTria2->GetEntityType() == SMDSEntity_Triangle))
+  {
     //  1 +--+ A  theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
     //    | /|    theTria2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
     //    |/ |                                         | \|
@@ -817,9 +805,9 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
     gp_Pnt xyz;
     if ( F.IsNull() )
     {
-      xyz = ( SMESH_TNodeXYZ( nodes[3] ) +
-              SMESH_TNodeXYZ( nodes[4] ) +
-              SMESH_TNodeXYZ( nodes[5] )) / 3.;
+      xyz = ( SMESH_NodeXYZ( nodes[3] ) +
+              SMESH_NodeXYZ( nodes[4] ) +
+              SMESH_NodeXYZ( nodes[5] )) / 3.;
     }
     else
     {
@@ -892,17 +880,16 @@ static bool findTriangles(const SMDS_MeshNode *    theNode1,
 bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
                                     const SMDS_MeshNode * theNode2)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   const SMDS_MeshElement *tr1, *tr2;
   if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
-  if (!F2) return false;
+  if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+    return false;
+
   if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
       (tr2->GetEntityType() == SMDSEntity_Triangle)) {
 
@@ -1013,35 +1000,33 @@ bool getQuadrangleNodes(const SMDS_MeshNode *    theQuadNodes [],
 bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
                                    const SMDS_MeshNode * theNode2)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   const SMDS_MeshElement *tr1, *tr2;
   if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
-  if (!F2) return false;
+  if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+    return false;
+
   SMESHDS_Mesh * aMesh = GetMeshDS();
 
   if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
-      (tr2->GetEntityType() == SMDSEntity_Triangle)) {
-
+      (tr2->GetEntityType() == SMDSEntity_Triangle))
+  {
     const SMDS_MeshNode* aNodes [ 4 ];
     if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
       return false;
 
     const SMDS_MeshElement* newElem = 0;
     newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3] );
-    myLastCreatedElems.Append(newElem);
+    myLastCreatedElems.push_back(newElem);
     AddToSameGroups( newElem, tr1, aMesh );
     int aShapeId = tr1->getshapeId();
     if ( aShapeId )
-      {
-        aMesh->SetMeshElementOnShape( newElem, aShapeId );
-      }
+      aMesh->SetMeshElementOnShape( newElem, aShapeId );
+
     aMesh->RemoveElement( tr1 );
     aMesh->RemoveElement( tr2 );
 
@@ -1085,13 +1070,13 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
   const SMDS_MeshElement* newElem = 0;
   newElem = aMesh->AddFace( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                             aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
-  myLastCreatedElems.Append(newElem);
+  myLastCreatedElems.push_back(newElem);
   AddToSameGroups( newElem, tr1, aMesh );
   int aShapeId = tr1->getshapeId();
   if ( aShapeId )
-    {
-      aMesh->SetMeshElementOnShape( newElem, aShapeId );
-    }
+  {
+    aMesh->SetMeshElementOnShape( newElem, aShapeId );
+  }
   aMesh->RemoveElement( tr1 );
   aMesh->RemoveElement( tr2 );
 
@@ -1108,8 +1093,7 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
 
 bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if (!theElem)
     return false;
@@ -1124,8 +1108,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
   const SMDSAbs_EntityType geomType = theElem->GetEntityType();
   if ( geomType == SMDSEntity_Polyhedra ) // polyhedron
   {
-    const SMDS_VtkVolume* aPolyedre =
-      dynamic_cast<const SMDS_VtkVolume*>( theElem );
+    const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( theElem );
     if (!aPolyedre) {
       MESSAGE("Warning: bad volumic element");
       return false;
@@ -1183,7 +1166,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
 
   if ( theFaces.empty() )
   {
-    SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true);
+    SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=true*/);
     while ( fIt->more() )
       theFaces.insert( theFaces.end(), fIt->next() );
   }
@@ -1278,7 +1261,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
         }
         if ( otherFace && otherFace != theFace)
         {
-          // link must be reverse in otherFace if orientation ot otherFace
+          // link must be reverse in otherFace if orientation to otherFace
           // is same as that of theFace
           if ( abs(nodeInd2-nodeInd1) == 1 ? nodeInd2 > nodeInd1 : nodeInd1 > nodeInd2 )
           {
@@ -1314,7 +1297,7 @@ int SMESH_MeshEditor::Reorient2DBy3D (TIDSortedElemSet & theFaces,
   if ( theFaces.empty() )
     faceIt = GetMeshDS()->elementsIterator( SMDSAbs_Face );
   else
-    faceIt = elemSetIterator( theFaces );
+    faceIt = SMESHUtils::elemSetIterator( theFaces );
 
   vector< const SMDS_MeshNode* > faceNodes;
   TIDSortedElemSet checkedVolumes;
@@ -1403,17 +1386,17 @@ static double getBadRate (const SMDS_MeshElement*               theElem,
 bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
                                   SMESH::Controls::NumericalFunctorPtr theCrit)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( !theCrit.get() )
     return false;
 
-  SMESHDS_Mesh * aMesh = GetMeshDS();
-
+  SMESHDS_Mesh *       aMesh = GetMeshDS();
   Handle(Geom_Surface) surface;
   SMESH_MesherHelper   helper( *GetMesh() );
 
+  myLastCreatedElems.reserve( theElems.size() * 2 );
+
   TIDSortedElemSet::iterator itElem;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
   {
@@ -1482,8 +1465,8 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
 
     // care of a new element
 
-    myLastCreatedElems.Append(newElem1);
-    myLastCreatedElems.Append(newElem2);
+    myLastCreatedElems.push_back(newElem1);
+    myLastCreatedElems.push_back(newElem2);
     AddToSameGroups( newElem1, elem, aMesh );
     AddToSameGroups( newElem2, elem, aMesh );
 
@@ -1500,21 +1483,21 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
 //=======================================================================
 /*!
  * \brief Split each of given quadrangles into 4 triangles.
- * \param theElems - The faces to be splitted. If empty all faces are split.
+ * \param theElems - The faces to be split. If empty all faces are split.
  */
 //=======================================================================
 
 void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
+  myLastCreatedElems.reserve( theElems.size() * 4 );
 
   SMESH_MesherHelper helper( *GetMesh() );
   helper.SetElementsOnShape( true );
 
   SMDS_ElemIteratorPtr faceIt;
   if ( theElems.empty() ) faceIt = GetMeshDS()->elementsIterator(SMDSAbs_Face);
-  else                    faceIt = elemSetIterator( theElems );
+  else                    faceIt = SMESHUtils::elemSetIterator( theElems );
 
   bool   checkUV;
   gp_XY  uv [9]; uv[8] = gp_XY(0,0);
@@ -1571,7 +1554,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
       if ( F.IsNull() )
       {
         for ( ; iN < nodes.size(); ++iN )
-          xyz[ iN ] = SMESH_TNodeXYZ( nodes[ iN ] );
+          xyz[ iN ] = SMESH_NodeXYZ( nodes[ iN ] );
 
         for ( ; iN < 8; ++iN ) // mid-side points of a linear qudrangle
           xyz[ iN ] = 0.5 * ( xyz[ iN - 4 ] + xyz[( iN - 3 )%4 ] );
@@ -1598,7 +1581,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
 
       nCentral = helper.AddNode( xyz[8].X(), xyz[8].Y(), xyz[8].Z(), /*id=*/0,
                                  uv[8].X(), uv[8].Y() );
-      myLastCreatedNodes.Append( nCentral );
+      myLastCreatedNodes.push_back( nCentral );
     }
 
     // create 4 triangles
@@ -1616,7 +1599,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
                                                nodes[(i+1)%4],
                                                nCentral );
       ReplaceElemInGroups( tria, quad, GetMeshDS() );
-      myLastCreatedElems.Append( tria );
+      myLastCreatedElems.push_back( tria );
     }
   }
 }
@@ -1629,8 +1612,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
 int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement*              theQuad,
                                  SMESH::Controls::NumericalFunctorPtr theCrit)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if (!theCrit.get())
     return -1;
@@ -1914,6 +1896,7 @@ namespace
         break;
       case SMDSEntity_Penta:
       case SMDSEntity_Quad_Penta:
+      case SMDSEntity_BiQuad_Penta:
         connVariants = thePentaTo3; nbTet = 3; nbVariants = 6;
         break;
       default:
@@ -2296,7 +2279,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
       volTool.GetBaryCenter( bc[0], bc[1], bc[2] );
       SMDS_MeshNode* gcNode = helper.AddNode( bc[0], bc[1], bc[2] );
       nodes.push_back( gcNode );
-      newNodes.Append( gcNode );
+      newNodes.push_back( gcNode );
     }
     if ( !splitMethod._faceBaryNode.empty() )
     {
@@ -2310,7 +2293,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
         if ( !f_n->second )
         {
           volTool.GetFaceBaryCenter( iF_n->first, bc[0], bc[1], bc[2] );
-          newNodes.Append( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
+          newNodes.push_back( f_n->second = helper.AddNode( bc[0], bc[1], bc[2] ));
         }
         nodes.push_back( iF_n->second = f_n->second );
       }
@@ -2321,18 +2304,18 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
     const int* volConn = splitMethod._connectivity;
     if ( splitMethod._nbCorners == 4 ) // tetra
       for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
-        newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
-                                                            nodes[ volConn[1] ],
-                                                            nodes[ volConn[2] ],
-                                                            nodes[ volConn[3] ]));
+        newElems.push_back( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
+                                                               nodes[ volConn[1] ],
+                                                               nodes[ volConn[2] ],
+                                                               nodes[ volConn[3] ]));
     else // prisms
       for ( int i = 0; i < splitMethod._nbSplits; ++i, volConn += splitMethod._nbCorners )
-        newElems.Append( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
-                                                            nodes[ volConn[1] ],
-                                                            nodes[ volConn[2] ],
-                                                            nodes[ volConn[3] ],
-                                                            nodes[ volConn[4] ],
-                                                            nodes[ volConn[5] ]));
+        newElems.push_back( splitVols[ i ] = helper.AddVolume( nodes[ volConn[0] ],
+                                                               nodes[ volConn[1] ],
+                                                               nodes[ volConn[2] ],
+                                                               nodes[ volConn[3] ],
+                                                               nodes[ volConn[4] ],
+                                                               nodes[ volConn[5] ]));
 
     ReplaceElemInGroups( elem, splitVols, GetMeshDS() );
 
@@ -2376,7 +2359,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
           if ( fSubMesh ) // update position of the bary node on geometry
           {
             if ( subMesh )
-              subMesh->RemoveNode( baryNode, false );
+              subMesh->RemoveNode( baryNode );
             GetMeshDS()->SetNodeOnFace( baryNode, fSubMesh->GetID() );
             const TopoDS_Shape& s = GetMeshDS()->IndexToShape( fSubMesh->GetID() );
             if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
@@ -2385,7 +2368,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
               gp_XY uv( 1e100, 1e100 );
               double distXYZ[4];
               if ( !fHelper.CheckNodeUV( TopoDS::Face( s ), baryNode,
-                                        uv, /*tol=*/1e-7, /*force=*/true, distXYZ ) &&
+                                         uv, /*tol=*/1e-7, /*force=*/true, distXYZ ) &&
                    uv.X() < 1e100 )
               {
                 // node is too far from the surface
@@ -2439,7 +2422,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
           if ( !triangles[ i ]) continue;
           if ( fSubMesh )
             fSubMesh->AddElement( triangles[ i ]);
-          newElems.Append( triangles[ i ]);
+          newElems.push_back( triangles[ i ]);
         }
         ReplaceElemInGroups( face, triangles, GetMeshDS() );
         GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false );
@@ -2476,7 +2459,7 @@ void SMESH_MeshEditor::GetHexaFacetsToSplit( TIDSortedElemSet& theHexas,
                                              const gp_Ax1&     theFacetNormal,
                                              TFacetOfElem &    theFacets)
 {
-  #define THIS_METHOD "SMESH_MeshEditor::GetHexaFacetsToSplit(): "
+#define THIS_METHOD "SMESH_MeshEditor::GetHexaFacetsToSplit(): "
 
   // Find a hexa closest to the location of theFacetNormal
 
@@ -2930,11 +2913,10 @@ void SMESH_MeshEditor::ReplaceElemInGroups (const SMDS_MeshElement*
 bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
                                   const bool         the13Diag)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
-
-  SMESHDS_Mesh * aMesh = GetMeshDS();
+  ClearLastCreated();
+  myLastCreatedElems.reserve( theElems.size() * 2 );
 
+  SMESHDS_Mesh *       aMesh = GetMeshDS();
   Handle(Geom_Surface) surface;
   SMESH_MesherHelper   helper( *GetMesh() );
 
@@ -2964,8 +2946,8 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
         newElem1 = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
         newElem2 = aMesh->AddFace( aNodes[3], aNodes[1], aNodes[2] );
       }
-      myLastCreatedElems.Append(newElem1);
-      myLastCreatedElems.Append(newElem2);
+      myLastCreatedElems.push_back(newElem1);
+      myLastCreatedElems.push_back(newElem2);
       // put a new triangle on the same shape and add to the same groups
       if ( aShapeId )
       {
@@ -3007,7 +2989,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
         centrNode = helper.GetCentralNode( aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                                            aNodes[4], aNodes[5], aNodes[6], aNodes[7],
                                            surface.IsNull() );
-        myLastCreatedNodes.Append(centrNode);
+        myLastCreatedNodes.push_back(centrNode);
       }
 
       // create a new element
@@ -3025,8 +3007,8 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
         newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
                                   centrNode, aNodes[5], aNodes[6] );
       }
-      myLastCreatedElems.Append(newElem1);
-      myLastCreatedElems.Append(newElem2);
+      myLastCreatedElems.push_back(newElem1);
+      myLastCreatedElems.push_back(newElem2);
       // put a new triangle on the same shape and add to the same groups
       if ( aShapeId )
       {
@@ -3150,8 +3132,8 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
                                   SMESH::Controls::NumericalFunctorPtr theCrit,
                                   const double                         theMaxAngle)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
+  myLastCreatedElems.reserve( theElems.size() / 2 );
 
   if ( !theCrit.get() )
     return false;
@@ -3335,7 +3317,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
           {
             const SMDS_MeshElement* newElem = 0;
             newElem = aMesh->AddFace(n12[0], n12[1], n12[2], n12[3] );
-            myLastCreatedElems.Append(newElem);
+            myLastCreatedElems.push_back(newElem);
             AddToSameGroups( newElem, tr1, aMesh );
             int aShapeId = tr1->getshapeId();
             if ( aShapeId )
@@ -3366,7 +3348,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             else
               newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                                        aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
-            myLastCreatedElems.Append(newElem);
+            myLastCreatedElems.push_back(newElem);
             AddToSameGroups( newElem, tr1, aMesh );
             int aShapeId = tr1->getshapeId();
             if ( aShapeId )
@@ -3389,7 +3371,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
           if ( tr1->NbNodes() == 3 ) {
             const SMDS_MeshElement* newElem = 0;
             newElem = aMesh->AddFace(n13[0], n13[1], n13[2], n13[3] );
-            myLastCreatedElems.Append(newElem);
+            myLastCreatedElems.push_back(newElem);
             AddToSameGroups( newElem, tr1, aMesh );
             int aShapeId = tr1->getshapeId();
             if ( aShapeId )
@@ -3420,7 +3402,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             else
               newElem = aMesh->AddFace(aNodes[0], aNodes[1], aNodes[2], aNodes[3],
                                        aNodes[4], aNodes[5], aNodes[6], aNodes[7]);
-            myLastCreatedElems.Append(newElem);
+            myLastCreatedElems.push_back(newElem);
             AddToSameGroups( newElem, tr1, aMesh );
             int aShapeId = tr1->getshapeId();
             if ( aShapeId )
@@ -3448,286 +3430,6 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
   return true;
 }
 
-
-/*#define DUMPSO(txt) \
-//  cout << txt << endl;
-//=============================================================================
-//
-//
-//
-//=============================================================================
-static void swap( int i1, int i2, int idNodes[], gp_Pnt P[] )
-{
-if ( i1 == i2 )
-return;
-int tmp = idNodes[ i1 ];
-idNodes[ i1 ] = idNodes[ i2 ];
-idNodes[ i2 ] = tmp;
-gp_Pnt Ptmp = P[ i1 ];
-P[ i1 ] = P[ i2 ];
-P[ i2 ] = Ptmp;
-DUMPSO( i1 << "(" << idNodes[ i2 ] << ") <-> " << i2 << "(" << idNodes[ i1 ] << ")");
-}
-
-//=======================================================================
-//function : SortQuadNodes
-//purpose  : Set 4 nodes of a quadrangle face in a good order.
-//           Swap 1<->2 or 2<->3 nodes and correspondingly return
-//           1 or 2 else 0.
-//=======================================================================
-
-int SMESH_MeshEditor::SortQuadNodes (const SMDS_Mesh * theMesh,
-int               idNodes[] )
-{
-  gp_Pnt P[4];
-  int i;
-  for ( i = 0; i < 4; i++ ) {
-    const SMDS_MeshNode *n = theMesh->FindNode( idNodes[i] );
-    if ( !n ) return 0;
-    P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
-  }
-
-  gp_Vec V1(P[0], P[1]);
-  gp_Vec V2(P[0], P[2]);
-  gp_Vec V3(P[0], P[3]);
-
-  gp_Vec Cross1 = V1 ^ V2;
-  gp_Vec Cross2 = V2 ^ V3;
-
-  i = 0;
-  if (Cross1.Dot(Cross2) < 0)
-  {
-    Cross1 = V2 ^ V1;
-    Cross2 = V1 ^ V3;
-
-    if (Cross1.Dot(Cross2) < 0)
-      i = 2;
-    else
-      i = 1;
-    swap ( i, i + 1, idNodes, P );
-
-    //     for ( int ii = 0; ii < 4; ii++ ) {
-    //       const SMDS_MeshNode *n = theMesh->FindNode( idNodes[ii] );
-    //       DUMPSO( ii << "(" << idNodes[ii] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
-    //     }
-  }
-  return i;
-}
-
-//=======================================================================
-//function : SortHexaNodes
-//purpose  : Set 8 nodes of a hexahedron in a good order.
-//           Return success status
-//=======================================================================
-
-bool SMESH_MeshEditor::SortHexaNodes (const SMDS_Mesh * theMesh,
-                                      int               idNodes[] )
-{
-  gp_Pnt P[8];
-  int i;
-  DUMPSO( "INPUT: ========================================");
-  for ( i = 0; i < 8; i++ ) {
-    const SMDS_MeshNode *n = theMesh->FindNode( idNodes[i] );
-    if ( !n ) return false;
-    P[ i ].SetCoord( n->X(), n->Y(), n->Z() );
-    DUMPSO( i << "(" << idNodes[i] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
-  }
-  DUMPSO( "========================================");
-
-
-  set<int> faceNodes;  // ids of bottom face nodes, to be found
-  set<int> checkedId1; // ids of tried 2-nd nodes
-  Standard_Real leastDist = DBL_MAX; // dist of the 4-th node from 123 plane
-  const Standard_Real tol = 1.e-6;   // tolerance to find nodes in plane
-  int iMin, iLoop1 = 0;
-
-  // Loop to try the 2-nd nodes
-
-  while ( leastDist > DBL_MIN && ++iLoop1 < 8 )
-  {
-    // Find not checked 2-nd node
-    for ( i = 1; i < 8; i++ )
-      if ( checkedId1.find( idNodes[i] ) == checkedId1.end() ) {
-        int id1 = idNodes[i];
-        swap ( 1, i, idNodes, P );
-        checkedId1.insert ( id1 );
-        break;
-      }
-
-    // Find the 3-d node so that 1-2-3 triangle to be on a hexa face,
-    // ie that all but meybe one (id3 which is on the same face) nodes
-    // lay on the same side from the triangle plane.
-
-    bool manyInPlane = false; // more than 4 nodes lay in plane
-    int iLoop2 = 0;
-    while ( ++iLoop2 < 6 ) {
-
-      // get 1-2-3 plane coeffs
-      Standard_Real A, B, C, D;
-      gp_Vec N = gp_Vec (P[0], P[1]).Crossed( gp_Vec (P[0], P[2]) );
-      if ( N.SquareMagnitude() > gp::Resolution() )
-      {
-        gp_Pln pln ( P[0], N );
-        pln.Coefficients( A, B, C, D );
-
-        // find the node (iMin) closest to pln
-        Standard_Real dist[ 8 ], minDist = DBL_MAX;
-        set<int> idInPln;
-        for ( i = 3; i < 8; i++ ) {
-          dist[i] = A * P[i].X() + B * P[i].Y() + C * P[i].Z() + D;
-          if ( fabs( dist[i] ) < minDist ) {
-            minDist = fabs( dist[i] );
-            iMin = i;
-          }
-          if ( fabs( dist[i] ) <= tol )
-            idInPln.insert( idNodes[i] );
-        }
-
-        // there should not be more than 4 nodes in bottom plane
-        if ( idInPln.size() > 1 )
-        {
-          DUMPSO( "### idInPln.size() = " << idInPln.size());
-          // idInPlane does not contain the first 3 nodes
-          if ( manyInPlane || idInPln.size() == 5)
-            return false; // all nodes in one plane
-          manyInPlane = true;
-
-          // set the 1-st node to be not in plane
-          for ( i = 3; i < 8; i++ ) {
-            if ( idInPln.find( idNodes[ i ] ) == idInPln.end() ) {
-              DUMPSO( "### Reset 0-th node");
-              swap( 0, i, idNodes, P );
-              break;
-            }
-          }
-
-          // reset to re-check second nodes
-          leastDist = DBL_MAX;
-          faceNodes.clear();
-          checkedId1.clear();
-          iLoop1 = 0;
-          break; // from iLoop2;
-        }
-
-        // check that the other 4 nodes are on the same side
-        bool sameSide = true;
-        bool isNeg = dist[ iMin == 3 ? 4 : 3 ] <= 0.;
-        for ( i = 3; sameSide && i < 8; i++ ) {
-          if ( i != iMin )
-            sameSide = ( isNeg == dist[i] <= 0.);
-        }
-
-        // keep best solution
-        if ( sameSide && minDist < leastDist ) {
-          leastDist = minDist;
-          faceNodes.clear();
-          faceNodes.insert( idNodes[ 1 ] );
-          faceNodes.insert( idNodes[ 2 ] );
-          faceNodes.insert( idNodes[ iMin ] );
-          DUMPSO( "loop " << iLoop2 << " id2 " << idNodes[ 1 ] << " id3 " << idNodes[ 2 ]
-                  << " leastDist = " << leastDist);
-          if ( leastDist <= DBL_MIN )
-            break;
-        }
-      }
-
-      // set next 3-d node to check
-      int iNext = 2 + iLoop2;
-      if ( iNext < 8 ) {
-        DUMPSO( "Try 2-nd");
-        swap ( 2, iNext, idNodes, P );
-      }
-    } // while ( iLoop2 < 6 )
-  } // iLoop1
-
-  if ( faceNodes.empty() ) return false;
-
-  // Put the faceNodes in proper places
-  for ( i = 4; i < 8; i++ ) {
-    if ( faceNodes.find( idNodes[ i ] ) != faceNodes.end() ) {
-      // find a place to put
-      int iTo = 1;
-      while ( faceNodes.find( idNodes[ iTo ] ) != faceNodes.end() )
-        iTo++;
-      DUMPSO( "Set faceNodes");
-      swap ( iTo, i, idNodes, P );
-    }
-  }
-
-
-  // Set nodes of the found bottom face in good order
-  DUMPSO( " Found bottom face: ");
-  i = SortQuadNodes( theMesh, idNodes );
-  if ( i ) {
-    gp_Pnt Ptmp = P[ i ];
-    P[ i ] = P[ i+1 ];
-    P[ i+1 ] = Ptmp;
-  }
-  //   else
-  //     for ( int ii = 0; ii < 4; ii++ ) {
-  //       const SMDS_MeshNode *n = theMesh->FindNode( idNodes[ii] );
-  //       DUMPSO( ii << "(" << idNodes[ii] <<") : "<<n->X()<<" "<<n->Y()<<" "<<n->Z());
-  //    }
-
-  // Gravity center of the top and bottom faces
-  gp_Pnt aGCb = ( P[0].XYZ() + P[1].XYZ() + P[2].XYZ() + P[3].XYZ() ) / 4.;
-  gp_Pnt aGCt = ( P[4].XYZ() + P[5].XYZ() + P[6].XYZ() + P[7].XYZ() ) / 4.;
-
-  // Get direction from the bottom to the top face
-  gp_Vec upDir ( aGCb, aGCt );
-  Standard_Real upDirSize = upDir.Magnitude();
-  if ( upDirSize <= gp::Resolution() ) return false;
-  upDir / upDirSize;
-
-  // Assure that the bottom face normal points up
-  gp_Vec Nb = gp_Vec (P[0], P[1]).Crossed( gp_Vec (P[0], P[2]) );
-  Nb += gp_Vec (P[0], P[2]).Crossed( gp_Vec (P[0], P[3]) );
-  if ( Nb.Dot( upDir ) < 0 ) {
-    DUMPSO( "Reverse bottom face");
-    swap( 1, 3, idNodes, P );
-  }
-
-  // Find 5-th node - the one closest to the 1-st among the last 4 nodes.
-  Standard_Real minDist = DBL_MAX;
-  for ( i = 4; i < 8; i++ ) {
-    // projection of P[i] to the plane defined by P[0] and upDir
-    gp_Pnt Pp = P[i].Translated( upDir * ( upDir.Dot( gp_Vec( P[i], P[0] ))));
-    Standard_Real sqDist = P[0].SquareDistance( Pp );
-    if ( sqDist < minDist ) {
-      minDist = sqDist;
-      iMin = i;
-    }
-  }
-  DUMPSO( "Set 4-th");
-  swap ( 4, iMin, idNodes, P );
-
-  // Set nodes of the top face in good order
-  DUMPSO( "Sort top face");
-  i = SortQuadNodes( theMesh, &idNodes[4] );
-  if ( i ) {
-    i += 4;
-    gp_Pnt Ptmp = P[ i ];
-    P[ i ] = P[ i+1 ];
-    P[ i+1 ] = Ptmp;
-  }
-
-  // Assure that direction of the top face normal is from the bottom face
-  gp_Vec Nt = gp_Vec (P[4], P[5]).Crossed( gp_Vec (P[4], P[6]) );
-  Nt += gp_Vec (P[4], P[6]).Crossed( gp_Vec (P[4], P[7]) );
-  if ( Nt.Dot( upDir ) < 0 ) {
-    DUMPSO( "Reverse top face");
-    swap( 5, 7, idNodes, P );
-  }
-
-  //   DUMPSO( "OUTPUT: ========================================");
-  //   for ( i = 0; i < 8; i++ ) {
-  //     float *p = ugrid->GetPoint(idNodes[i]);
-  //     DUMPSO( i << "(" << idNodes[i] << ") : " << p[0] << " " << p[1] << " " << p[2]);
-  //   }
-
-  return true;
-}*/
-
 //================================================================================
 /*!
  * \brief Return nodes linked to the given one
@@ -3933,8 +3635,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
                                double                      theTgtAspectRatio,
                                const bool                  the2D)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( theTgtAspectRatio < 1.0 )
     theTgtAspectRatio = 1.0;
@@ -4127,7 +3828,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         // }
         if ( project ) { // compute new UV
           gp_XY newUV;
-          gp_Pnt pNode = SMESH_TNodeXYZ( node );
+          gp_Pnt pNode = SMESH_NodeXYZ( node );
           if ( !getClosestUV( projector, pNode, newUV )) {
             MESSAGE("Node Projection Failed " << node);
           }
@@ -4140,7 +3841,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
             // if ( posType != SMDS_TOP_3DSPACE )
             //   dist2 = pNode.SquareDistance( surface->Value( newUV.X(), newUV.Y() ));
             // if ( dist2 < dist1 )
-              uv = newUV;
+            uv = newUV;
           }
         }
         // store UV in the map
@@ -4382,7 +4083,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         const SMDS_MeshElement* QF = *elemIt;
         if ( QF->IsQuadratic() )
         {
-          nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesElemIterator() ),
+          nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesIterator() ),
                         SMDS_MeshElement::iterator() );
           nodes.push_back( nodes[0] );
           gp_Pnt xyz;
@@ -4396,9 +4097,9 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
               xyz = surface->Value( uv.X(), uv.Y() );
             }
             else {
-              xyz = 0.5 * ( SMESH_TNodeXYZ( nodes[i-1] ) + SMESH_TNodeXYZ( nodes[i+1] ));
+              xyz = 0.5 * ( SMESH_NodeXYZ( nodes[i-1] ) + SMESH_NodeXYZ( nodes[i+1] ));
             }
-            if (( SMESH_TNodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
+            if (( SMESH_NodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
               // we have to move a medium node
               aMesh->MoveNode( nodes[i], xyz.X(), xyz.Y(), xyz.Z() );
           }
@@ -4426,8 +4127,8 @@ namespace
                  const int                           iNotSame)
   {
 
-    SMESH_TNodeXYZ pP = prevNodes[ iNotSame ];
-    SMESH_TNodeXYZ pN = nextNodes[ iNotSame ];
+    SMESH_NodeXYZ pP = prevNodes[ iNotSame ];
+    SMESH_NodeXYZ pN = nextNodes[ iNotSame ];
     gp_XYZ extrDir( pN - pP ), faceNorm;
     SMESH_MeshAlgos::FaceNormal( face, faceNorm, /*normalized=*/false );
 
@@ -4568,11 +4269,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         std::swap( itNN[0],    itNN[1] );
         std::swap( prevNod[0], prevNod[1] );
         std::swap( nextNod[0], nextNod[1] );
-#if defined(__APPLE__)
         std::swap( isSingleNode[0], isSingleNode[1] );
-#else
-        isSingleNode.swap( isSingleNode[0], isSingleNode[1] );
-#endif
         if ( nbSame > 0 )
           sames[0] = 1 - sames[0];
         iNotSameNode = 1 - iNotSameNode;
@@ -4664,55 +4361,55 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         break;
       }
       case SMDSEntity_Triangle: // TRIANGLE --->
-        {
-          if ( nbDouble > 0 ) break;
-          if ( nbSame == 0 )       // ---> pentahedron
-            aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
-                                         nextNod[ 0 ], nextNod[ 1 ], nextNod[ 2 ] );
-
-          else if ( nbSame == 1 )  // ---> pyramid
-            aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
-                                         nextNod[ iAfterSame ],  nextNod[ iBeforeSame ],
-                                         nextNod[ iSameNode ]);
-
-          else // 2 same nodes:       ---> tetrahedron
-            aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
-                                         nextNod[ iNotSameNode ]);
-          break;
-        }
+      {
+        if ( nbDouble > 0 ) break;
+        if ( nbSame == 0 )       // ---> pentahedron
+          aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
+                                       nextNod[ 0 ], nextNod[ 1 ], nextNod[ 2 ] );
+
+        else if ( nbSame == 1 )  // ---> pyramid
+          aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
+                                       nextNod[ iAfterSame ],  nextNod[ iBeforeSame ],
+                                       nextNod[ iSameNode ]);
+
+        else // 2 same nodes:       ---> tetrahedron
+          aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
+                                       nextNod[ iNotSameNode ]);
+        break;
+      }
       case SMDSEntity_Quad_Edge: // sweep quadratic EDGE --->
+      {
+        if ( nbSame == 2 )
+          return;
+        if ( nbDouble+nbSame == 2 )
         {
-          if ( nbSame == 2 )
-            return;
-          if ( nbDouble+nbSame == 2 )
-          {
-            if(nbSame==0) {      // ---> quadratic quadrangle
-              aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
-                                        prevNod[2], midlNod[1], nextNod[2], midlNod[0]);
-            }
-            else { //(nbSame==1) // ---> quadratic triangle
-              if(sames[0]==2) {
-                return; // medium node on axis
-              }
-              else if(sames[0]==0)
-                aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1],
-                                          prevNod[2], midlNod[1], nextNod[2] );
-              else // sames[0]==1
-                aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[0],
-                                          prevNod[2], nextNod[2], midlNod[0]);
-            }
+          if(nbSame==0) {      // ---> quadratic quadrangle
+            aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
+                                      prevNod[2], midlNod[1], nextNod[2], midlNod[0]);
           }
-          else if ( nbDouble == 3 )
-          {
-            if ( nbSame == 0 ) {  // ---> bi-quadratic quadrangle
-              aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
-                                        prevNod[2], midlNod[1], nextNod[2], midlNod[0], midlNod[2]);
+          else { //(nbSame==1) // ---> quadratic triangle
+            if(sames[0]==2) {
+              return; // medium node on axis
             }
+            else if(sames[0]==0)
+              aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1],
+                                        prevNod[2], midlNod[1], nextNod[2] );
+            else // sames[0]==1
+              aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[0],
+                                        prevNod[2], nextNod[2], midlNod[0]);
+          }
+        }
+        else if ( nbDouble == 3 )
+        {
+          if ( nbSame == 0 ) {  // ---> bi-quadratic quadrangle
+            aNewElem = aMesh->AddFace(prevNod[0], prevNod[1], nextNod[1], nextNod[0],
+                                      prevNod[2], midlNod[1], nextNod[2], midlNod[0], midlNod[2]);
           }
-          else
-            return;
-          break;
         }
+        else
+          return;
+        break;
+      }
       case SMDSEntity_Quadrangle: { // sweep QUADRANGLE --->
         if ( nbDouble > 0 ) break;
 
@@ -4934,8 +4631,8 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
 
     if ( aNewElem ) {
       newElems.push_back( aNewElem );
-      myLastCreatedElems.Append(aNewElem);
-      srcElements.Append( elem );
+      myLastCreatedElems.push_back(aNewElem);
+      srcElements.push_back( elem );
     }
 
     // set new prev nodes
@@ -5025,19 +4722,19 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
       if ( !isQuadratic ) {
         if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
                                vecNewNodes[ 1 ]->second.back())) {
-          myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
-                                                   vecNewNodes[ 1 ]->second.back()));
-          srcElements.Append( elem );
+          myLastCreatedElems.push_back(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+                                                      vecNewNodes[ 1 ]->second.back()));
+          srcElements.push_back( elem );
         }
       }
       else {
         if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
                                vecNewNodes[ 1 ]->second.back(),
                                vecNewNodes[ 2 ]->second.back())) {
-          myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
-                                                   vecNewNodes[ 1 ]->second.back(),
-                                                   vecNewNodes[ 2 ]->second.back()));
-          srcElements.Append( elem );
+          myLastCreatedElems.push_back(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+                                                      vecNewNodes[ 1 ]->second.back(),
+                                                      vecNewNodes[ 2 ]->second.back()));
+          srcElements.push_back( elem );
         }
       }
     }
@@ -5065,14 +4762,14 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
           // make a new edge and a ceiling for a new edge
           const SMDS_MeshElement* edge;
           if ( ! ( edge = aMesh->FindEdge( n1, n2 ))) {
-            myLastCreatedElems.Append( edge = aMesh->AddEdge( n1, n2 )); // free link edge
-            srcElements.Append( myLastCreatedElems.Last() );
+            myLastCreatedElems.push_back( edge = aMesh->AddEdge( n1, n2 )); // free link edge
+            srcElements.push_back( myLastCreatedElems.back() );
           }
           n1 = vecNewNodes[ iNode ]->second.back();
           n2 = vecNewNodes[ iNext ]->second.back();
           if ( !aMesh->FindEdge( n1, n2 )) {
-            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2 )); // new edge ceiling
-            srcElements.Append( edge );
+            myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2 )); // new edge ceiling
+            srcElements.push_back( edge );
           }
         }
       }
@@ -5093,15 +4790,15 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
           // make an edge and a ceiling for a new edge
           // find medium node
           if ( !aMesh->FindEdge( n1, n2, n3 )) {
-            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // free link edge
-            srcElements.Append( elem );
+            myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2, n3 )); // free link edge
+            srcElements.push_back( elem );
           }
           n1 = vecNewNodes[ iNode ]->second.back();
           n2 = vecNewNodes[ iNext ]->second.back();
           n3 = vecNewNodes[ iNode+nbn ]->second.back();
           if ( !aMesh->FindEdge( n1, n2, n3 )) {
-            myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
-            srcElements.Append( elem );
+            myLastCreatedElems.push_back(aMesh->AddEdge( n1, n2, n3 )); // ceiling edge
+            srcElements.push_back( elem );
           }
         }
       }
@@ -5135,9 +4832,9 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         SMDS_VolumeTool vTool( *v, /*ignoreCentralNodes=*/false );
         int iF, nbF = vTool.NbFaces();
         for ( iF = 0; iF < nbF; iF ++ ) {
-          if (vTool.IsFreeFace( iF ) &&
-              vTool.GetFaceNodes( iF, faceNodeSet ) &&
-              initNodeSet != faceNodeSet) // except an initial face
+          if ( vTool.IsFreeFace( iF ) &&
+               vTool.GetFaceNodes( iF, faceNodeSet ) &&
+               initNodeSet != faceNodeSet) // except an initial face
           {
             if ( nbSteps == 1 && faceNodeSet == topNodeSet )
               continue;
@@ -5194,8 +4891,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
-                                                            newOrder[ 2 ] ));
+                  myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+                                                               newOrder[ 2 ] ));
               }
             }
             else if ( nbn == 4 )       ///// quadrangle
@@ -5209,8 +4906,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
-                                                            newOrder[ 2 ], newOrder[ 3 ]));
+                  myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+                                                               newOrder[ 2 ], newOrder[ 3 ]));
               }
             }
             else if ( nbn == 6 && isQuadratic ) /////// quadratic triangle
@@ -5228,12 +4925,12 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ],
-                                                            newOrder[ 1 ],
-                                                            newOrder[ 2 ],
-                                                            newOrder[ 3 ],
-                                                            newOrder[ 4 ],
-                                                            newOrder[ 5 ] ));
+                  myLastCreatedElems.push_back(aMesh->AddFace( newOrder[ 0 ],
+                                                               newOrder[ 1 ],
+                                                               newOrder[ 2 ],
+                                                               newOrder[ 3 ],
+                                                               newOrder[ 4 ],
+                                                               newOrder[ 5 ] ));
               }
             }
             else if ( nbn == 8 && isQuadratic ) /////// quadratic quadrangle
@@ -5254,10 +4951,10 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
-                                                           newOrder[ 2 ], newOrder[ 3 ],
-                                                           newOrder[ 4 ], newOrder[ 5 ],
-                                                           newOrder[ 6 ], newOrder[ 7 ]));
+                  myLastCreatedElems.push_back(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
+                                                              newOrder[ 2 ], newOrder[ 3 ],
+                                                              newOrder[ 4 ], newOrder[ 5 ],
+                                                              newOrder[ 6 ], newOrder[ 7 ]));
               }
             }
             else if ( nbn == 9 && isQuadratic ) /////// bi-quadratic quadrangle
@@ -5279,11 +4976,11 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                 if ( f )
                   aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
                 else
-                  myLastCreatedElems.Append(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
-                                                           newOrder[ 2 ], newOrder[ 3 ],
-                                                           newOrder[ 4 ], newOrder[ 5 ],
-                                                           newOrder[ 6 ], newOrder[ 7 ],
-                                                           newOrder[ 8 ]));
+                  myLastCreatedElems.push_back(aMesh->AddFace(newOrder[ 0 ], newOrder[ 1 ],
+                                                              newOrder[ 2 ], newOrder[ 3 ],
+                                                              newOrder[ 4 ], newOrder[ 5 ],
+                                                              newOrder[ 6 ], newOrder[ 7 ],
+                                                              newOrder[ 8 ]));
               }
             }
             else  //////// polygon
@@ -5302,8 +4999,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
               }
             }
 
-            while ( srcElements.Length() < myLastCreatedElems.Length() )
-              srcElements.Append( *srcEdge );
+            while ( srcElements.size() < myLastCreatedElems.size() )
+              srcElements.push_back( *srcEdge );
 
           }  // loop on free faces
 
@@ -5340,8 +5037,8 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
 
         AddElement( nodeVec, anyFace.Init( elem ));
 
-        while ( srcElements.Length() < myLastCreatedElems.Length() )
-          srcElements.Append( elem );
+        while ( srcElements.size() < myLastCreatedElems.size() )
+          srcElements.push_back( elem );
       }
     }
   } // loop on swept elements
@@ -5361,11 +5058,16 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
                                 const bool         theMakeGroups,
                                 const bool         theMakeWalls)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
+
+  setElemsFirst( theElemSets );
+  myLastCreatedElems.reserve( theElemSets[0].size() * theNbSteps );
+  myLastCreatedNodes.reserve( theElemSets[1].size() * theNbSteps );
 
   // source elements for each generated one
   SMESH_SequenceOfElemPtr srcElems, srcNodes;
+  srcElems.reserve( theElemSets[0].size() );
+  srcNodes.reserve( theElemSets[1].size() );
 
   gp_Trsf aTrsf;
   aTrsf.SetRotation( theAxis, theAngle );
@@ -5385,7 +5087,6 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
                                      myMesh->NbFaces(ORDER_QUADRATIC) +
                                      myMesh->NbVolumes(ORDER_QUADRATIC) );
   // loop on theElemSets
-  setElemsFirst( theElemSets );
   TIDSortedElemSet::iterator itElem;
   for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
   {
@@ -5437,8 +5138,8 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
               {
                 aTrsf2.Transforms( coord[0], coord[1], coord[2] );
                 newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-                myLastCreatedNodes.Append(newNode);
-                srcNodes.Append( node );
+                myLastCreatedNodes.push_back(newNode);
+                srcNodes.push_back( node );
                 listNewNodes.push_back( newNode );
                 aTrsf2.Transforms( coord[0], coord[1], coord[2] );
               }
@@ -5447,8 +5148,8 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
               }
               // create a corner node
               newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-              myLastCreatedNodes.Append(newNode);
-              srcNodes.Append( node );
+              myLastCreatedNodes.push_back(newNode);
+              srcNodes.push_back( node );
               listNewNodes.push_back( newNode );
             }
             else {
@@ -5622,7 +5323,7 @@ void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& el
         while ( itN->more() ) {
           const SMDS_MeshElement* node = itN->next();
           if ( newNodes.insert( node ).second )
-            myBaseP += SMESH_TNodeXYZ( node );
+            myBaseP += SMESH_NodeXYZ( node );
         }
       }
     }
@@ -5688,7 +5389,7 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
                 std::list<const SMDS_MeshNode*> & newNodes,
                 const bool                        makeMediumNodes)
 {
-  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ p = SMESH_NodeXYZ( srcNode );
 
   int nbNodes = 0;
   for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
@@ -5725,7 +5426,7 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
       iSc += int( makeMediumNodes );
       ScaleIt& scale = scales[ iSc % 2 ];
       
-      gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
+      gp_XYZ xyz = SMESH_NodeXYZ( *nIt );
       xyz = ( *scale * ( xyz - center )) + center;
       mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
 
@@ -5746,7 +5447,7 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
                       std::list<const SMDS_MeshNode*> & newNodes,
                       const bool                        makeMediumNodes)
 {
-  gp_XYZ P1 = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ P1 = SMESH_NodeXYZ( srcNode );
 
   int nbNodes = 0;
   for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
@@ -5754,13 +5455,14 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
     P1 += myDir.XYZ() * nextStep();
 
     // try to search in sequence of existing nodes
-    // if myNodes.Length()>0 we 'nave to use given sequence
+    // if myNodes.size()>0 we 'nave to use given sequence
     // else - use all nodes of mesh
     const SMDS_MeshNode * node = 0;
-    if ( myNodes.Length() > 0 ) {
-      int i;
-      for(i=1; i<=myNodes.Length(); i++) {
-        gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) );
+    if ( myNodes.Length() > 0 )
+    {
+      for ( int i = 1; i <= myNodes.Length(); i++ )
+      {
+        SMESH_NodeXYZ P2 = myNodes.Value(i);
         if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
         {
           node = myNodes.Value(i);
@@ -5768,10 +5470,12 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
         }
       }
     }
-    else {
+    else
+    {
       SMDS_NodeIteratorPtr itn = mesh->nodesIterator();
-      while(itn->more()) {
-        SMESH_TNodeXYZ P2( itn->next() );
+      while(itn->more())
+      {
+        SMESH_NodeXYZ P2 = itn->next();
         if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
         {
           node = P2._node;
@@ -5803,7 +5507,7 @@ makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
 {
   const bool alongAvgNorm = ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL );
 
-  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ p = SMESH_NodeXYZ( srcNode );
 
   // get normals to faces sharing srcNode
   vector< gp_XYZ > norms, baryCenters;
@@ -5823,7 +5527,7 @@ makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
         gp_XYZ bc(0,0,0);
         int nbN = 0;
         for ( SMDS_ElemIteratorPtr nIt = face->nodesIterator(); nIt->more(); ++nbN )
-          bc += SMESH_TNodeXYZ( nIt->next() );
+          bc += SMESH_NodeXYZ( nIt->next() );
         baryCenters.push_back( bc / nbN );
       }
     }
@@ -5921,13 +5625,17 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
                                   ExtrusParam&         theParams,
                                   TTElemOfElemListMap& newElemsMap)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
+
+  setElemsFirst( theElemSets );
+  myLastCreatedElems.reserve( theElemSets[0].size() * theParams.NbSteps() );
+  myLastCreatedNodes.reserve( theElemSets[1].size() * theParams.NbSteps() );
 
   // source elements for each generated one
   SMESH_SequenceOfElemPtr srcElems, srcNodes;
+  srcElems.reserve( theElemSets[0].size() );
+  srcNodes.reserve( theElemSets[1].size() );
 
-  setElemsFirst( theElemSets );
   const int nbSteps = theParams.NbSteps();
   theParams.SetElementsToUse( theElemSets[0], theElemSets[1] );
 
@@ -5986,8 +5694,8 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
             list<const SMDS_MeshNode*>::iterator newNodesIt = listNewNodes.begin();
             for ( ; newNodesIt != listNewNodes.end(); ++newNodesIt )
             {
-              myLastCreatedNodes.Append( *newNodesIt );
-              srcNodes.Append( node );
+              myLastCreatedNodes.push_back( *newNodesIt );
+              srcNodes.push_back( node );
             }
           }
           else
@@ -6028,8 +5736,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
                                        const gp_Pnt&        theRefPoint,
                                        const bool           theMakeGroups)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   int aNbE;
   std::list<double> aPrms;
@@ -6088,9 +5795,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       return EXTR_BAD_STARTING_NODE;
     aItN = pSubMeshDS->GetNodes();
     while ( aItN->more() ) {
-      const SMDS_MeshNode* pNode = aItN->next();
-      const SMDS_EdgePosition* pEPos =
-        static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+      const SMDS_MeshNode*  pNode = aItN->next();
+      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
       double aT = pEPos->GetUParameter();
       aPrms.push_back( aT );
     }
@@ -6133,8 +5839,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         aItN = locMeshDS->GetNodes();
         while ( aItN->more() ) {
           const SMDS_MeshNode* pNode = aItN->next();
-          const SMDS_EdgePosition* pEPos =
-            static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
           double aT = pEPos->GetUParameter();
           aPrms.push_back( aT );
         }
@@ -6143,7 +5848,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
         LLPPs.push_back(LPP);
         UsedNums.Add(k);
-        // update startN for search following egde
+        // update startN for search following edge
         if( aN1->GetID() == startNid ) startNid = aN2->GetID();
         else startNid = aN1->GetID();
         break;
@@ -6203,8 +5908,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
                                        const gp_Pnt&        theRefPoint,
                                        const bool           theMakeGroups)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   int aNbE;
   std::list<double> aPrms;
@@ -6257,7 +5961,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     SMDS_ElemIteratorPtr nIt;
 
     //check start node
-    if( !theTrack->GetMeshDS()->Contains(theN1) ) {
+    if( !theTrack->GetMeshDS()->Contains( theN1 )) {
       return EXTR_BAD_STARTING_NODE;
     }
 
@@ -6317,8 +6021,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     int startNid = theN1->GetID();
     for ( size_t i = 1; i < aNodesList.size(); i++ )
     {
-      gp_Pnt     p1 = SMESH_TNodeXYZ( aNodesList[i-1] );
-      gp_Pnt     p2 = SMESH_TNodeXYZ( aNodesList[i] );
+      gp_Pnt     p1 = SMESH_NodeXYZ( aNodesList[i-1] );
+      gp_Pnt     p2 = SMESH_NodeXYZ( aNodesList[i] );
       TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
       list<SMESH_MeshEditor_PathPoint> LPP;
       aPrms.clear();
@@ -6374,8 +6078,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     while ( aItN->more() ) {
       const SMDS_MeshNode* pNode = aItN->next();
       if( pNode==aN1 || pNode==aN2 ) continue;
-      const SMDS_EdgePosition* pEPos =
-        static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
       double aT = pEPos->GetUParameter();
       aPrms.push_back( aT );
     }
@@ -6431,9 +6134,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         aPrms.clear();
         aItN = locMeshDS->GetNodes();
         while ( aItN->more() ) {
-          const SMDS_MeshNode*     pNode = aItN->next();
-          const SMDS_EdgePosition* pEPos =
-            static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+          const SMDS_MeshNode*  pNode = aItN->next();
+          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
           double aT = pEPos->GetUParameter();
           aPrms.push_back( aT );
         }
@@ -6442,7 +6144,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
         LLPPs.push_back(LPP);
         UsedNums.Add(k);
-        // update startN for search following egde
+        // update startN for search following edge
         if ( aN1isOK ) aVprev = aV2;
         else           aVprev = aV1;
         break;
@@ -6591,7 +6293,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
         while ( itN->more() ) {
           const SMDS_MeshElement* node = itN->next();
           if ( newNodes.insert( node ).second )
-            aGC += SMESH_TNodeXYZ( node );
+            aGC += SMESH_NodeXYZ( node );
         }
       }
     }
@@ -6635,7 +6337,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
           aTolAng=1.e-4;
 
           aV0x = aV0;
-          aPN0 = SMESH_TNodeXYZ( node );
+          aPN0 = SMESH_NodeXYZ( node );
 
           const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
           aP0x = aPP0.Pnt();
@@ -6683,13 +6385,13 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
               // create additional node
               gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
               const SMDS_MeshNode* newNode = aMesh->AddNode( midP.X(), midP.Y(), midP.Z() );
-              myLastCreatedNodes.Append(newNode);
-              srcNodes.Append( node );
+              myLastCreatedNodes.push_back(newNode);
+              srcNodes.push_back( node );
               listNewNodes.push_back( newNode );
             }
             const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
-            myLastCreatedNodes.Append(newNode);
-            srcNodes.Append( node );
+            myLastCreatedNodes.push_back(newNode);
+            srcNodes.push_back( node );
             listNewNodes.push_back( newNode );
 
             aPN0 = aPN1;
@@ -6715,8 +6417,8 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
               double y = ( N->Y() + P.Y() )/2.;
               double z = ( N->Z() + P.Z() )/2.;
               const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
-              srcNodes.Append( node );
-              myLastCreatedNodes.Append(newN);
+              srcNodes.push_back( node );
+              myLastCreatedNodes.push_back(newN);
               aNodes[2*i] = newN;
               aNodes[2*i+1] = N;
               P = gp_XYZ(N->X(),N->Y(),N->Z());
@@ -6809,8 +6511,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
                              const bool         theMakeGroups,
                              SMESH_Mesh*        theTargetMesh)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
+  myLastCreatedElems.reserve( theElems.size() );
 
   bool needReverse = false;
   string groupPostfix;
@@ -6905,14 +6607,14 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
         if ( theTargetMesh ) {
           const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
           n2n_isnew.first->second = newNode;
-          myLastCreatedNodes.Append(newNode);
-          srcNodes.Append( node );
+          myLastCreatedNodes.push_back(newNode);
+          srcNodes.push_back( node );
         }
         else if ( theCopy ) {
           const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
           n2n_isnew.first->second = newNode;
-          myLastCreatedNodes.Append(newNode);
-          srcNodes.Append( node );
+          myLastCreatedNodes.push_back(newNode);
+          srcNodes.push_back( node );
         }
         else {
           aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
@@ -6955,8 +6657,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
     if ( geomType == SMDSGeom_POLYHEDRA )  // ------------------ polyhedral volume
     {
-      const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
-      if (!aPolyedre)
+      const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem );
+      if ( !aPolyedre )
         continue;
       nodes.clear();
       bool allTransformed = true;
@@ -7002,7 +6704,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     if ( editor ) {
       // copy in this or a new mesh
       if ( editor->AddElement( nodes, elemType.Init( elem, /*basicOnly=*/false )))
-        srcElems.Append( elem );
+        srcElems.push_back( elem );
     }
     else {
       // reverse element as it was reversed by transformation
@@ -7013,7 +6715,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
   } // loop on elements
 
   if ( editor && editor != this )
-    myLastCreatedElems = editor->myLastCreatedElems;
+    myLastCreatedElems.swap( editor->myLastCreatedElems );
 
   PGroupIDs newGroupIDs;
 
@@ -7024,14 +6726,97 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
   return newGroupIDs;
 }
 
+//================================================================================
+/*!
+ * \brief Make an offset mesh from a source 2D mesh
+ *  \param [in] theElements - source faces
+ *  \param [in] theValue - offset value
+ *  \param [out] theTgtMesh - a mesh to add offset elements to
+ *  \param [in] theMakeGroups - to generate groups
+ *  \return PGroupIDs - IDs of created groups
+ */
+//================================================================================
+
+SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElements,
+                                                      const double       theValue,
+                                                      SMESH_Mesh*        theTgtMesh,
+                                                      const bool         theMakeGroups,
+                                                      const bool         theFixSelfIntersection)
+{
+  SMESHDS_Mesh*    meshDS = GetMeshDS();
+  SMESHDS_Mesh* tgtMeshDS = theTgtMesh->GetMeshDS();
+  SMESH_MeshEditor tgtEditor( theTgtMesh );
+
+  SMDS_ElemIteratorPtr eIt;
+  if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+  else                       eIt = SMESHUtils::elemSetIterator( theElements );
+
+  SMESH_MeshAlgos::TEPairVec new2OldFaces;
+  SMESH_MeshAlgos::TNPairVec new2OldNodes;
+  std::unique_ptr< SMDS_Mesh > offsetMesh
+    ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
+                                   theFixSelfIntersection,
+                                   new2OldFaces, new2OldNodes ));
+
+  offsetMesh->Modified();
+  offsetMesh->CompactMesh(); // make IDs start from 1
+
+  // source elements for each generated one
+  SMESH_SequenceOfElemPtr srcElems, srcNodes;
+  srcElems.reserve( new2OldFaces.size() );
+  srcNodes.reserve( new2OldNodes.size() );
+
+  ClearLastCreated();
+  myLastCreatedElems.reserve( new2OldFaces.size() );
+  myLastCreatedNodes.reserve( new2OldNodes.size() );
+
+  // copy offsetMesh to theTgtMesh
+
+  int idShift = meshDS->MaxNodeID();
+  for ( size_t i = 0; i < new2OldNodes.size(); ++i )
+    if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
+    {
+      if ( n->NbInverseElements() > 0 )
+      {
+        const SMDS_MeshNode* n2 =
+          tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
+        myLastCreatedNodes.push_back( n2 );
+        srcNodes.push_back( new2OldNodes[ i ].second );
+      }
+    }
+
+  ElemFeatures elemType;
+  for ( size_t i = 0; i < new2OldFaces.size(); ++i )
+    if ( const SMDS_MeshElement* f = new2OldFaces[ i ].first )
+    {
+      elemType.Init( f );
+      elemType.myNodes.clear();
+      for ( SMDS_NodeIteratorPtr nIt = f->nodeIterator(); nIt->more(); )
+      {
+        const SMDS_MeshNode* n2 = nIt->next();
+        elemType.myNodes.push_back( tgtMeshDS->FindNode( idShift + n2->GetID() ));
+      }
+      tgtEditor.AddElement( elemType.myNodes, elemType );
+      srcElems.push_back( new2OldFaces[ i ].second );
+    }
+
+  myLastCreatedElems.swap( tgtEditor.myLastCreatedElems );
+
+  PGroupIDs newGroupIDs;
+  if ( theMakeGroups )
+    newGroupIDs = generateGroups( srcNodes, srcElems, "offset", theTgtMesh, false );
+
+  return newGroupIDs;
+}
+
 //=======================================================================
 /*!
  * \brief Create groups of elements made during transformation
  *  \param nodeGens - nodes making corresponding myLastCreatedNodes
  *  \param elemGens - elements making corresponding myLastCreatedElems
- *  \param postfix - to append to names of new groups
+ *  \param postfix - to push_back to names of new groups
  *  \param targetMesh - mesh to create groups in
- *  \param topPresent - is there "top" elements that are created by sweeping
+ *  \param topPresent - is there are "top" elements that are created by sweeping
  */
 //=======================================================================
 
@@ -7084,30 +6869,30 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
   {
     const SMESH_SequenceOfElemPtr& gens  = isNodes ? nodeGens : elemGens;
     const SMESH_SequenceOfElemPtr& elems = isNodes ? myLastCreatedNodes : myLastCreatedElems;
-    if ( gens.Length() != elems.Length() )
+    if ( gens.size() != elems.size() )
       throw SALOME_Exception("SMESH_MeshEditor::generateGroups(): invalid args");
 
     // loop on created elements
-    for (int iElem = 1; iElem <= elems.Length(); ++iElem )
+    for (size_t iElem = 0; iElem < elems.size(); ++iElem )
     {
-      const SMDS_MeshElement* sourceElem = gens( iElem );
+      const SMDS_MeshElement* sourceElem = gens[ iElem ];
       if ( !sourceElem ) {
         MESSAGE("generateGroups(): NULL source element");
         continue;
       }
       list< TOldNewGroup > & groupsOldNew = groupsByType[ sourceElem->GetType() ];
       if ( groupsOldNew.empty() ) { // no groups of this type at all
-        while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
+        while ( iElem+1 < gens.size() && gens[ iElem+1 ] == sourceElem )
           ++iElem; // skip all elements made by sourceElem
         continue;
       }
       // collect all elements made by the iElem-th sourceElem
       resultElems.clear();
-      if ( const SMDS_MeshElement* resElem = elems( iElem ))
+      if ( const SMDS_MeshElement* resElem = elems[ iElem ])
         if ( resElem != sourceElem )
           resultElems.push_back( resElem );
-      while ( iElem < gens.Length() && gens( iElem+1 ) == sourceElem )
-        if ( const SMDS_MeshElement* resElem = elems( ++iElem ))
+      while ( iElem+1 < gens.size() && gens[ iElem+1 ] == sourceElem )
+        if ( const SMDS_MeshElement* resElem = elems[ ++iElem ])
           if ( resElem != sourceElem )
             resultElems.push_back( resElem );
 
@@ -7147,7 +6932,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
           {
             SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
             newTopGroup.Add( topElem );
-         }
+          }
         }
       }
     } // loop on created elements
@@ -7234,8 +7019,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
                                             TListOfListOfNodes & theGroupsOfNodes,
                                             bool                 theSeparateCornersAndMedium)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( myMesh->NbEdges  ( ORDER_QUADRATIC ) +
        myMesh->NbFaces  ( ORDER_QUADRATIC ) +
@@ -7248,7 +7032,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
   if ( theNodes.empty() ) // get all nodes in the mesh
   {
     TIDSortedNodeSet* nodes[2] = { &corners, &medium };
-    SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true);
+    SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator();
     if ( theSeparateCornersAndMedium )
       while ( nIt->more() )
       {
@@ -7348,8 +7132,7 @@ int SMESH_MeshEditor::SimplifyFace (const vector<const SMDS_MeshNode *>& faceNod
 void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
                                    const bool           theAvoidMakingHoles)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   SMESHDS_Mesh* mesh = GetMeshDS();
 
@@ -7385,8 +7168,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
     const SMDS_MeshNode* nToKeep = nnIt->second;
     TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep );
     while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second )
+    {
       nToKeep = nnIt_i->second;
-    nnIt->second = nToKeep;
+      nnIt->second = nToKeep;
+      nnIt_i = nodeNodeMap.find( nToKeep );
+    }
   }
 
   if ( theAvoidMakingHoles )
@@ -7437,7 +7223,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
       AddToSameGroups( nToKeep, nToRemove, mesh );
       // set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing
       // w/o creating node in place of merged ones.
-      const SMDS_PositionPtr& pos = nToRemove->GetPosition();
+      SMDS_PositionPtr pos = nToRemove->GetPosition();
       if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
         if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
           sm->SetIsAlwaysComputed( true );
@@ -7625,7 +7411,7 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
       if ( nbUniqueNodes >= 4 )
       {
         // each face has to be analyzed in order to check volume validity
-        if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ))
+        if ( const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem ))
         {
           int nbFaces = aPolyedre->NbFaces();
 
@@ -7943,26 +7729,55 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
 
 
 // ========================================================
-// class   : SortableElement
-// purpose : allow sorting elements basing on their nodes
+// class   : ComparableElement
+// purpose : allow comparing elements basing on their nodes
 // ========================================================
-class SortableElement : public set <const SMDS_MeshElement*>
+
+class ComparableElement : public boost::container::flat_set< int >
 {
+  typedef boost::container::flat_set< int >  int_set;
+
+  const SMDS_MeshElement* myElem;
+  int                     mySumID;
+  mutable int             myGroupID;
+
 public:
 
-  SortableElement( const SMDS_MeshElement* theElem )
+  ComparableElement( const SMDS_MeshElement* theElem ):
+    myElem ( theElem ), mySumID( 0 ), myGroupID( -1 )
   {
-    myElem = theElem;
-    SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
-    while ( nodeIt->more() )
-      this->insert( nodeIt->next() );
+    this->reserve( theElem->NbNodes() );
+    for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); )
+    {
+      int id = nodeIt->next()->GetID();
+      mySumID += id;
+      this->insert( id );
+    }
   }
 
-  const SMDS_MeshElement* Get() const
-  { return myElem; }
+  const SMDS_MeshElement* GetElem() const { return myElem; }
+
+  int& GroupID() const { return myGroupID; }
+  //int& GroupID() const { return const_cast< int& >( myGroupID ); }
+
+  ComparableElement( const ComparableElement& theSource ) // move copy
+  {
+    ComparableElement& src = const_cast< ComparableElement& >( theSource );
+    (int_set&) (*this ) = boost::move( src );
+    myElem    = src.myElem;
+    mySumID   = src.mySumID;
+    myGroupID = src.myGroupID;
+  }
+
+  static int HashCode(const ComparableElement& se, int limit )
+  {
+    return ::HashCode( se.mySumID, limit );
+  }
+  static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 )
+  {
+    return ( se1 == se2 );
+  }
 
-private:
-  mutable const SMDS_MeshElement* myElem;
 };
 
 //=======================================================================
@@ -7971,53 +7786,47 @@ private:
 //           Search among theElements or in the whole mesh if theElements is empty
 //=======================================================================
 
-void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
-                                         TListOfListOfElementsID & theGroupsOfElementsID)
+void SMESH_MeshEditor::FindEqualElements( TIDSortedElemSet &        theElements,
+                                          TListOfListOfElementsID & theGroupsOfElementsID )
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
-
-  typedef map< SortableElement, int > TMapOfNodeSet;
-  typedef list<int> TGroupOfElems;
+  ClearLastCreated();
 
-  if ( theElements.empty() )
-  { // get all elements in the mesh
-    SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
-    while ( eIt->more() )
-      theElements.insert( theElements.end(), eIt->next() );
-  }
+  SMDS_ElemIteratorPtr elemIt;
+  if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator();
+  else                       elemIt = SMESHUtils::elemSetIterator( theElements );
 
-  vector< TGroupOfElems > arrayOfGroups;
-  TGroupOfElems groupOfElems;
-  TMapOfNodeSet mapOfNodeSet;
+  typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements;
+  typedef std::list<int>                                          TGroupOfElems;
+  TMapOfElements               mapOfElements;
+  std::vector< TGroupOfElems > arrayOfGroups;
+  TGroupOfElems                groupOfElems;
 
-  TIDSortedElemSet::iterator elemIt = theElements.begin();
-  for ( int i = 0; elemIt != theElements.end(); ++elemIt )
+  while ( elemIt->more() )
   {
-    const SMDS_MeshElement* curElem = *elemIt;
-    SortableElement SE(curElem);
+    const SMDS_MeshElement* curElem = elemIt->next();
+    ComparableElement      compElem = curElem;
     // check uniqueness
-    pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, i));
-    if ( !pp.second ) { // one more coincident elem
-      TMapOfNodeSet::iterator& itSE = pp.first;
-      int ind = (*itSE).second;
-      arrayOfGroups[ind].push_back( curElem->GetID() );
-    }
-    else {
-      arrayOfGroups.push_back( groupOfElems );
-      arrayOfGroups.back().push_back( curElem->GetID() );
-      i++;
+    const ComparableElement& elemInSet = mapOfElements.Added( compElem );
+    if ( elemInSet.GetElem() != curElem ) // coincident elem
+    {
+      int& iG = elemInSet.GroupID();
+      if ( iG < 0 )
+      {
+        iG = arrayOfGroups.size();
+        arrayOfGroups.push_back( groupOfElems );
+        arrayOfGroups[ iG ].push_back( elemInSet.GetElem()->GetID() );
+      }
+      arrayOfGroups[ iG ].push_back( curElem->GetID() );
     }
   }
 
   groupOfElems.clear();
-  vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
+  std::vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
   for ( ; groupIt != arrayOfGroups.end(); ++groupIt )
   {
     if ( groupIt->size() > 1 ) {
-      //groupOfElems.sort(); -- theElements is sorted already
-      theGroupsOfElementsID.push_back( groupOfElems );
-      theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt );
+      //groupOfElems.sort(); -- theElements are sorted already
+      theGroupsOfElementsID.emplace_back( *groupIt );
     }
   }
 }
@@ -8029,8 +7838,7 @@ void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
 
 void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElementsID)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   typedef list<int> TListOfIDs;
   TListOfIDs rmElemIds; // IDs of elems to remove
@@ -8069,8 +7877,8 @@ void SMESH_MeshEditor::MergeEqualElements()
   TIDSortedElemSet aMeshElements; /* empty input ==
                                      to merge equal elements in the whole mesh */
   TListOfListOfElementsID aGroupsOfElementsID;
-  FindEqualElements(aMeshElements, aGroupsOfElementsID);
-  MergeElements(aGroupsOfElementsID);
+  FindEqualElements( aMeshElements, aGroupsOfElementsID );
+  MergeElements( aGroupsOfElementsID );
 }
 
 //=======================================================================
@@ -8148,24 +7956,11 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
       if ( e == curElem || foundElems.insert( e ).second ) {
         // get nodes
         int iNode = 0, nbNodes = e->NbNodes();
-        vector<const SMDS_MeshNode*> nodes(nbNodes+1);
-
-        if ( e->IsQuadratic() ) {
-          const SMDS_VtkFace* F =
-            dynamic_cast<const SMDS_VtkFace*>(e);
-          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-          // use special nodes iterator
-          SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-          while( anIter->more() ) {
-            nodes[ iNode++ ] = cast2Node(anIter->next());
-          }
-        }
-        else {
-          SMDS_ElemIteratorPtr nIt = e->nodesIterator();
-          while ( nIt->more() )
-            nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
-        }
-        nodes[ iNode ] = nodes[ 0 ];
+        vector<const SMDS_MeshNode*> nodes( nbNodes+1 );
+        nodes.assign( SMDS_MeshElement::iterator( e->interlacedNodesIterator() ),
+                      SMDS_MeshElement::iterator() );
+        nodes.push_back( nodes[ 0 ]);
+
         // check 2 links
         for ( iNode = 0; iNode < nbNodes; iNode++ )
           if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
@@ -8232,7 +8027,7 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
       if ( contNodes[0].empty() && contNodes[1].empty() )
         return false;
 
-      // append the best free border
+      // push_back the best free border
       cNL = & contNodes[ contNodes[0].empty() ? 1 : 0 ];
       cFL = & contFaces[ contFaces[0].empty() ? 1 : 0 ];
       theNodes.pop_back(); // remove nIgnore
@@ -8282,8 +8077,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
                                  const bool           toCreatePolygons,
                                  const bool           toCreatePolyedrs)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   Sew_Error aResult = SEW_OK;
 
@@ -8423,27 +8217,13 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0];
         if ( isVolume ) // --volume
           hasVolumes = true;
-        else if ( elem->GetType()==SMDSAbs_Face ) { // --face
+        else if ( elem->GetType() == SMDSAbs_Face ) { // --face
           // retrieve all face nodes and find iPrevNode - an index of the prevSideNode
-          if(elem->IsQuadratic()) {
-            const SMDS_VtkFace* F =
-              dynamic_cast<const SMDS_VtkFace*>(elem);
-            if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-            // use special nodes iterator
-            SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-            while( anIter->more() ) {
-              nodes[ iNode ] = cast2Node(anIter->next());
-              if ( nodes[ iNode++ ] == prevSideNode )
-                iPrevNode = iNode - 1;
-            }
-          }
-          else {
-            SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
-            while ( nIt->more() ) {
-              nodes[ iNode ] = cast2Node( nIt->next() );
-              if ( nodes[ iNode++ ] == prevSideNode )
-                iPrevNode = iNode - 1;
-            }
+          SMDS_NodeIteratorPtr nIt = elem->interlacedNodesIterator();
+          while ( nIt->more() ) {
+            nodes[ iNode ] = cast2Node( nIt->next() );
+            if ( nodes[ iNode++ ] == prevSideNode )
+              iPrevNode = iNode - 1;
           }
           // there are 2 links to check
           nbNodes = 2;
@@ -8736,19 +8516,20 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
   // get new segments
   TIDSortedElemSet segments;
   SMESH_SequenceOfElemPtr newFaces;
-  for ( int i = 1; i <= myLastCreatedElems.Length(); ++i )
+  for ( size_t i = 0; i < myLastCreatedElems.size(); ++i )
   {
-    if ( !myLastCreatedElems(i) ) continue;
-    if ( myLastCreatedElems(i)->GetType() == SMDSAbs_Edge )
-      segments.insert( segments.end(), myLastCreatedElems(i) );
+    if ( !myLastCreatedElems[i] ) continue;
+    if ( myLastCreatedElems[i]->GetType() == SMDSAbs_Edge )
+      segments.insert( segments.end(), myLastCreatedElems[i] );
     else
-      newFaces.Append( myLastCreatedElems(i) );
+      newFaces.push_back( myLastCreatedElems[i] );
   }
   // get segments adjacent to merged nodes
   TListOfListOfNodes::iterator groupIt = nodeGroupsToMerge.begin();
   for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ )
   {
     const list<const SMDS_MeshNode*>& nodes = *groupIt;
+    if ( nodes.front()->IsNull() ) continue;
     SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge );
     while ( segIt->more() )
       segments.insert( segIt->next() );
@@ -8777,7 +8558,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     myLastCreatedElems = newFaces;
     TIDSortedElemSet::iterator seg = segments.begin();
     for ( ; seg != segments.end(); ++seg )
-      myLastCreatedElems.Append( *seg );
+      myLastCreatedElems.push_back( *seg );
   }
 
   return aResult;
@@ -8847,7 +8628,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theElemen
       if ( newElems[i] )
       {
         aMesh->SetMeshElementOnShape( newElems[i], theElement->getshapeId() );
-        myLastCreatedElems.Append( newElems[i] );
+        myLastCreatedElems.push_back( newElems[i] );
       }
     ReplaceElemInGroups( theElement, newElems, aMesh );
     aMesh->RemoveElement( theElement );
@@ -8903,48 +8684,21 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theElemen
 
     // add nodes of face up to first node of link
     bool isFLN = false;
-
-    if ( theFace->IsQuadratic() ) {
-      const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(theFace);
-      if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-      // use special nodes iterator
-      SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-      while( anIter->more()  && !isFLN ) {
-        const SMDS_MeshNode* n = cast2Node(anIter->next());
-        poly_nodes[iNode++] = n;
-        if (n == nodes[il1]) {
-          isFLN = true;
-        }
-      }
-      // add nodes to insert
-      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-      for (; nIt != aNodesToInsert.end(); nIt++) {
-        poly_nodes[iNode++] = *nIt;
-      }
-      // add nodes of face starting from last node of link
-      while ( anIter->more() ) {
-        poly_nodes[iNode++] = cast2Node(anIter->next());
-      }
+    SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator();
+    while ( nodeIt->more() && !isFLN ) {
+      const SMDS_MeshNode* n = nodeIt->next();
+      poly_nodes[iNode++] = n;
+      isFLN = ( n == nodes[il1] );
     }
-    else {
-      SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
-      while ( nodeIt->more() && !isFLN ) {
-        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-        poly_nodes[iNode++] = n;
-        if (n == nodes[il1]) {
-          isFLN = true;
-        }
-      }
-      // add nodes to insert
-      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-      for (; nIt != aNodesToInsert.end(); nIt++) {
-        poly_nodes[iNode++] = *nIt;
-      }
-      // add nodes of face starting from last node of link
-      while ( nodeIt->more() ) {
-        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-        poly_nodes[iNode++] = n;
-      }
+    // add nodes to insert
+    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+    for (; nIt != aNodesToInsert.end(); nIt++) {
+      poly_nodes[iNode++] = *nIt;
+    }
+    // add nodes of face starting from last node of link
+    while ( nodeIt->more() ) {
+      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+      poly_nodes[iNode++] = n;
     }
 
     // make a new face
@@ -9108,7 +8862,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theElemen
     if ( newElems[i] )
     {
       aMesh->SetMeshElementOnShape( newElems[i], theFace->getshapeId() );
-      myLastCreatedElems.Append( newElems[i] );
+      myLastCreatedElems.push_back( newElems[i] );
     }
   ReplaceElemInGroups( theFace, newElems, aMesh );
   aMesh->RemoveElement(theFace);
@@ -9124,8 +8878,7 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
                                       const SMDS_MeshNode*        theBetweenNode2,
                                       list<const SMDS_MeshNode*>& theNodesToInsert)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   SMDS_ElemIteratorPtr invElemIt = theBetweenNode1->GetInverseElementIterator(SMDSAbs_Volume);
   while (invElemIt->more()) { // loop on inverse elements of theBetweenNode1
@@ -9187,7 +8940,7 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
     if ( SMDS_MeshElement* newElem = aMesh->AddPolyhedralVolume( poly_nodes, quantities ))
     {
       aMesh->SetMeshElementOnShape( newElem, elem->getshapeId() );
-      myLastCreatedElems.Append( newElem );
+      myLastCreatedElems.push_back( newElem );
       ReplaceElemInGroups( elem, newElem, aMesh );
     }
     aMesh->RemoveElement( elem );
@@ -9229,6 +8982,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
                                              SMESH_MesherHelper& theHelper,
                                              const bool          theForce3d)
 {
+  //MESSAGE("convertElemToQuadratic");
   int nbElem = 0;
   if( !theSm ) return nbElem;
 
@@ -9254,18 +9008,20 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
       case SMDSEntity_Quad_Triangle:
       case SMDSEntity_Quad_Quadrangle:
       case SMDSEntity_Quad_Hexa:
+      case SMDSEntity_Quad_Penta:
         alreadyOK = !theHelper.GetIsBiQuadratic(); break;
 
       case SMDSEntity_BiQuad_Triangle:
       case SMDSEntity_BiQuad_Quadrangle:
       case SMDSEntity_TriQuad_Hexa:
+      case SMDSEntity_BiQuad_Penta:
         alreadyOK = theHelper.GetIsBiQuadratic();
         hasCentralNodes = true;
         break;
       default:
         alreadyOK = true;
       }
-      // take into account already present modium nodes
+      // take into account already present medium nodes
       switch ( aType ) {
       case SMDSAbs_Volume:
         theHelper.AddTLinks( static_cast< const SMDS_MeshVolume* >( elem )); break;
@@ -9284,7 +9040,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     const int nbNodes = elem->NbCornerNodes();
     nodes.assign(elem->begin_nodes(), elem->end_nodes());
     if ( aGeomType == SMDSEntity_Polyhedra )
-      nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+      nbNodeInFaces = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
     else if ( aGeomType == SMDSEntity_Hexagonal_Prism )
       volumeToPolyhedron( elem, nodes, nbNodeInFaces );
 
@@ -9302,50 +9058,52 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     switch( aType )
     {
     case SMDSAbs_Edge :
-      {
-        NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
-        break;
-      }
+    {
+      NewElem = theHelper.AddEdge(nodes[0], nodes[1], id, theForce3d);
+      break;
+    }
     case SMDSAbs_Face :
+    {
+      switch(nbNodes)
       {
-        switch(nbNodes)
-        {
-        case 3:
-          NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
-          break;
-        case 4:
-          NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
-          break;
-        default:
-          NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
-        }
+      case 3:
+        NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
+        break;
+      case 4:
+        NewElem = theHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
         break;
+      default:
+        NewElem = theHelper.AddPolygonalFace(nodes, id, theForce3d);
       }
+      break;
+    }
     case SMDSAbs_Volume :
+    {
+      switch( aGeomType )
       {
-        switch( aGeomType )
-        {
-        case SMDSEntity_Tetra:
-          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
-          break;
-        case SMDSEntity_Pyramid:
-          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
-          break;
-        case SMDSEntity_Penta:
-          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
-          break;
-        case SMDSEntity_Hexa:
-        case SMDSEntity_Quad_Hexa:
-        case SMDSEntity_TriQuad_Hexa:
-          NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
-                                        nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
-          break;
-        case SMDSEntity_Hexagonal_Prism:
-        default:
-          NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
-        }
+      case SMDSEntity_Tetra:
+        NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
         break;
+      case SMDSEntity_Pyramid:
+        NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
+        break;
+      case SMDSEntity_Penta:
+      case SMDSEntity_Quad_Penta:
+      case SMDSEntity_BiQuad_Penta:
+        NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
+        break;
+      case SMDSEntity_Hexa:
+      case SMDSEntity_Quad_Hexa:
+      case SMDSEntity_TriQuad_Hexa:
+        NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
+        break;
+      case SMDSEntity_Hexagonal_Prism:
+      default:
+        NewElem = theHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
       }
+      break;
+    }
     default :
       continue;
     }
@@ -9362,6 +9120,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
 
 void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theToBiQuad)
 {
+  //MESSAGE("ConvertToQuadratic "<< theForce3d << " " << theToBiQuad);
   SMESHDS_Mesh* meshDS = GetMeshDS();
 
   SMESH_MesherHelper aHelper(*myMesh);
@@ -9489,6 +9248,8 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
         {
         case SMDSEntity_Quad_Hexa:    alreadyOK = !theToBiQuad; break;
         case SMDSEntity_TriQuad_Hexa: alreadyOK = theToBiQuad; break;
+        case SMDSEntity_Quad_Penta:   alreadyOK = !theToBiQuad; break;
+        case SMDSEntity_BiQuad_Penta: alreadyOK = theToBiQuad; break;
         default:                      alreadyOK = true;
         }
         if ( alreadyOK )
@@ -9500,7 +9261,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
       const int id = volume->GetID();
       vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
       if ( type == SMDSEntity_Polyhedra )
-        nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
+        nbNodeInFaces = static_cast<const SMDS_MeshVolume* >(volume)->GetQuantities();
       else if ( type == SMDSEntity_Hexagonal_Prism )
         volumeToPolyhedron( volume, nodes, nbNodeInFaces );
 
@@ -9526,8 +9287,13 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
                                       nodes[3], nodes[4], id, theForce3d);
         break;
       case SMDSEntity_Penta:
+      case SMDSEntity_Quad_Penta:
+      case SMDSEntity_BiQuad_Penta:
         NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                       nodes[3], nodes[4], nodes[5], id, theForce3d);
+        for ( size_t i = 15; i < nodes.size(); ++i ) // rm central nodes
+          if ( nodes[i]->NbInverseElements() == 0 )
+            GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true );
         break;
       case SMDSEntity_Hexagonal_Prism:
       default:
@@ -9715,7 +9481,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
     if( newElem && smDS )
       smDS->AddElement( newElem );
 
-     // remove central nodes
+    // remove central nodes
     for ( size_t i = nodes.size() - nbCentralNodes; i < nodes.size(); ++i )
       if ( nodes[i]->NbInverseElements() == 0 )
         meshDS->RemoveFreeNode( nodes[i], smDS, /*fromGroups=*/true );
@@ -9849,7 +9615,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements)
   }
 
   // replace given elements by linear ones
-  SMDS_ElemIteratorPtr elemIt = elemSetIterator( theElements );
+  SMDS_ElemIteratorPtr elemIt = SMESHUtils::elemSetIterator( theElements );
   removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
 
   // we need to convert remaining elements whose all medium nodes are in mediumNodeIDs
@@ -9901,7 +9667,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements)
       }
     }
   }
-  elemIt = elemSetIterator( moreElemsToConvert );
+  elemIt = SMESHUtils::elemSetIterator( moreElemsToConvert );
   removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
 }
 
@@ -9918,8 +9684,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
                                    const SMDS_MeshNode* theSecondNode1,
                                    const SMDS_MeshNode* theSecondNode2)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( theSide1.size() != theSide2.size() )
     return SEW_DIFF_NB_OF_ELEMENTS;
@@ -10195,12 +9960,12 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
 
   if ( faceSet1.size() != faceSet2.size() ) {
     // delete temporary faces: they are in reverseElements of actual nodes
-//    SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
-//    while ( tmpFaceIt->more() )
-//      aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
-//    list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
-//    for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
-//      aMesh->RemoveElement(*tmpFaceIt);
+    //    SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
+    //    while ( tmpFaceIt->more() )
+    //      aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
+    //    list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
+    //    for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
+    //      aMesh->RemoveElement(*tmpFaceIt);
     MESSAGE("Diff nb of faces");
     return SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
   }
@@ -10258,20 +10023,8 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
         //cout << " F " << face[ iSide]->GetID() <<endl;
         faceSetPtr[ iSide ]->erase( face[ iSide ]);
         // put face nodes to fnodes
-        if ( face[ iSide ]->IsQuadratic() )
-        {
-          // use interlaced nodes iterator
-          const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>( face[ iSide ]);
-          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-          SMDS_ElemIteratorPtr nIter = F->interlacedNodesElemIterator();
-          while ( nIter->more() )
-            fnodes[ iSide ].push_back( cast2Node( nIter->next() ));
-        }
-        else
-        {
-          fnodes[ iSide ].assign( face[ iSide ]->begin_nodes(),
-                                  face[ iSide ]->end_nodes() );
-        }
+        SMDS_MeshElement::iterator nIt( face[ iSide ]->interlacedNodesIterator() ), nEnd;
+        fnodes[ iSide ].assign( nIt, nEnd );
         fnodes[ iSide ].push_back( fnodes[ iSide ].front());
       }
     }
@@ -10339,7 +10092,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
 
   if ( aResult == SEW_OK &&
        ( //linkIt[0] != linkList[0].end() ||
-         !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
+        !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
     MESSAGE( (linkIt[0] != linkList[0].end()) <<" "<< (faceSetPtr[0]->empty()) <<
              " " << (faceSetPtr[1]->empty()));
     aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
@@ -10350,9 +10103,9 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   // ====================================================================
 
   // delete temporary faces
-//  SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
-//  while ( tmpFaceIt->more() )
-//    aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
+  //  SMDS_FaceIteratorPtr tmpFaceIt = aTmpFacesMesh.facesIterator();
+  //  while ( tmpFaceIt->more() )
+  //    aTmpFacesMesh.RemoveElement( tmpFaceIt->next() );
   list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
   for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
     aMesh->RemoveElement(*tmpFaceIt);
@@ -10584,6 +10337,559 @@ SMESH_MeshEditor::FindMatchingNodes(set<const SMDS_MeshElement*>& theSide1,
   return SEW_OK;
 }
 
+namespace // automatically find theAffectedElems for DoubleNodes()
+{
+  bool isOut( const SMDS_MeshNode* n, const gp_XYZ& norm, const SMDS_MeshElement* elem );
+
+  //--------------------------------------------------------------------------------
+  // Nodes shared by adjacent FissureBorder's.
+  // 1 node  if FissureBorder separates faces
+  // 2 nodes if FissureBorder separates volumes
+  struct SubBorder
+  {
+    const SMDS_MeshNode* _nodes[2];
+    int                  _nbNodes;
+
+    SubBorder( const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 = 0 )
+    {
+      _nodes[0] = n1;
+      _nodes[1] = n2;
+      _nbNodes = bool( n1 ) + bool( n2 );
+      if ( _nbNodes == 2 && n1 > n2 )
+        std::swap( _nodes[0], _nodes[1] );
+    }
+    bool operator<( const SubBorder& other ) const
+    {
+      for ( int i = 0; i < _nbNodes; ++i )
+      {
+        if ( _nodes[i] < other._nodes[i] ) return true;
+        if ( _nodes[i] > other._nodes[i] ) return false;
+      }
+      return false;
+    }
+  };
+
+  //--------------------------------------------------------------------------------
+  // Map a SubBorder to all FissureBorder it bounds
+  struct FissureBorder;
+  typedef std::map< SubBorder, std::vector< FissureBorder* > > TBorderLinks;
+  typedef TBorderLinks::iterator                               TMappedSub;
+
+  //--------------------------------------------------------------------------------
+  /*!
+   * \brief Element border (volume facet or face edge) at a fissure
+   */
+  struct FissureBorder
+  {
+    std::vector< const SMDS_MeshNode* > _nodes;    // border nodes
+    const SMDS_MeshElement*             _elems[2]; // volume or face adjacent to fissure
+
+    std::vector< TMappedSub           > _mappedSubs;  // Sub() in TBorderLinks map
+    std::vector< const SMDS_MeshNode* > _sortedNodes; // to compare FissureBorder's
+
+    FissureBorder( FissureBorder && from ) // move constructor
+    {
+      std::swap( _nodes,       from._nodes );
+      std::swap( _sortedNodes, from._sortedNodes );
+      _elems[0] = from._elems[0];
+      _elems[1] = from._elems[1];
+    }
+
+    FissureBorder( const SMDS_MeshElement*                  elemToDuplicate,
+                   std::vector< const SMDS_MeshElement* > & adjElems)
+      : _nodes( elemToDuplicate->NbCornerNodes() )
+    {
+      for ( size_t i = 0; i < _nodes.size(); ++i )
+        _nodes[i] = elemToDuplicate->GetNode( i );
+
+      SMDSAbs_ElementType type = SMDSAbs_ElementType( elemToDuplicate->GetType() + 1 );
+      findAdjacent( type, adjElems );
+    }
+
+    FissureBorder( const SMDS_MeshNode**                    nodes,
+                   const size_t                             nbNodes,
+                   const SMDSAbs_ElementType                adjElemsType,
+                   std::vector< const SMDS_MeshElement* > & adjElems)
+      : _nodes( nodes, nodes + nbNodes )
+    {
+      findAdjacent( adjElemsType, adjElems );
+    }
+
+    void findAdjacent( const SMDSAbs_ElementType                adjElemsType,
+                       std::vector< const SMDS_MeshElement* > & adjElems)
+    {
+      _elems[0] = _elems[1] = 0;
+      adjElems.clear();
+      if ( SMDS_Mesh::GetElementsByNodes( _nodes, adjElems, adjElemsType ))
+        for ( size_t i = 0; i < adjElems.size() && i < 2; ++i )
+          _elems[i] = adjElems[i];
+    }
+
+    bool operator<( const FissureBorder& other ) const
+    {
+      return GetSortedNodes() < other.GetSortedNodes();
+    }
+
+    const std::vector< const SMDS_MeshNode* >& GetSortedNodes() const
+    {
+      if ( _sortedNodes.empty() && !_nodes.empty() )
+      {
+        FissureBorder* me = const_cast<FissureBorder*>( this );
+        me->_sortedNodes = me->_nodes;
+        std::sort( me->_sortedNodes.begin(), me->_sortedNodes.end() );
+      }
+      return _sortedNodes;
+    }
+
+    size_t NbSub() const
+    {
+      return _nodes.size();
+    }
+
+    SubBorder Sub(size_t i) const
+    {
+      return SubBorder( _nodes[i], NbSub() > 2 ? _nodes[ (i+1)%NbSub() ] : 0 );
+    }
+
+    void AddSelfTo( TBorderLinks& borderLinks )
+    {
+      _mappedSubs.resize( NbSub() );
+      for ( size_t i = 0; i < NbSub(); ++i )
+      {
+        TBorderLinks::iterator s2b =
+          borderLinks.insert( std::make_pair( Sub(i), TBorderLinks::mapped_type() )).first;
+        s2b->second.push_back( this );
+        _mappedSubs[ i ] = s2b;
+      }
+    }
+
+    void Clear()
+    {
+      _nodes.clear();
+    }
+
+    const SMDS_MeshElement* GetMarkedElem() const
+    {
+      if ( _nodes.empty() ) return 0; // cleared
+      if ( _elems[0] && _elems[0]->isMarked() ) return _elems[0];
+      if ( _elems[1] && _elems[1]->isMarked() ) return _elems[1];
+      return 0;
+    }
+
+    gp_XYZ GetNorm() const // normal to the border
+    {
+      gp_XYZ norm;
+      if ( _nodes.size() == 2 )
+      {
+        gp_XYZ avgNorm( 0,0,0 ); // sum of normals of adjacent faces
+        if ( SMESH_MeshAlgos::FaceNormal( _elems[0], norm ))
+          avgNorm += norm;
+        if ( SMESH_MeshAlgos::FaceNormal( _elems[1], norm ))
+          avgNorm += norm;
+
+        gp_XYZ bordDir( SMESH_NodeXYZ( _nodes[0] ) - SMESH_NodeXYZ( _nodes[1] ));
+        norm = bordDir ^ avgNorm;
+      }
+      else
+      {
+        SMESH_NodeXYZ p0( _nodes[0] );
+        SMESH_NodeXYZ p1( _nodes[1] );
+        SMESH_NodeXYZ p2( _nodes[2] );
+        norm = ( p0 - p1 ) ^ ( p2 - p1 );
+      }
+      if ( isOut( _nodes[0], norm, GetMarkedElem() ))
+        norm.Reverse();
+
+      return norm;
+    }
+
+    void ChooseSide() // mark an _elem located at positive side of fissure
+    {
+      _elems[0]->setIsMarked( true );
+      gp_XYZ norm = GetNorm();
+      double maxX = norm.Coord(1);
+      if ( Abs( maxX ) < Abs( norm.Coord(2)) ) maxX = norm.Coord(2);
+      if ( Abs( maxX ) < Abs( norm.Coord(3)) ) maxX = norm.Coord(3);
+      if ( maxX < 0 )
+      {
+        _elems[0]->setIsMarked( false );
+        _elems[1]->setIsMarked( true );
+      }
+    }
+
+  }; // struct FissureBorder
+
+  //--------------------------------------------------------------------------------
+  /*!
+   * \brief Classifier of elements at fissure edge
+   */
+  class FissureNormal
+  {
+    std::vector< gp_XYZ > _normals;
+    bool                  _bothIn;
+
+  public:
+    void Add( const SMDS_MeshNode* n, const FissureBorder& bord )
+    {
+      _bothIn = false;
+      _normals.reserve(2);
+      _normals.push_back( bord.GetNorm() );
+      if ( _normals.size() == 2 )
+        _bothIn = !isOut( n, _normals[0], bord.GetMarkedElem() );
+    }
+
+    bool IsIn( const SMDS_MeshNode* n, const SMDS_MeshElement* elem ) const
+    {
+      bool isIn = false;
+      switch ( _normals.size() ) {
+      case 1:
+      {
+        isIn = !isOut( n, _normals[0], elem );
+        break;
+      }
+      case 2:
+      {
+        bool in1 = !isOut( n, _normals[0], elem );
+        bool in2 = !isOut( n, _normals[1], elem );
+        isIn = _bothIn ? ( in1 && in2 ) : ( in1 || in2 );
+      }
+      }
+      return isIn;
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Classify an element by a plane passing through a node
+   */
+  //================================================================================
+
+  bool isOut( const SMDS_MeshNode* n, const gp_XYZ& norm, const SMDS_MeshElement* elem )
+  {
+    SMESH_NodeXYZ p = n;
+    double sumDot = 0;
+    for ( int i = 0, nb = elem->NbCornerNodes(); i < nb; ++i )
+    {
+      SMESH_NodeXYZ pi = elem->GetNode( i );
+      sumDot += norm * ( pi - p );
+    }
+    return sumDot < -1e-100;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Find FissureBorder's by nodes to duplicate
+   */
+  //================================================================================
+
+  void findFissureBorders( const TIDSortedElemSet&        theNodes,
+                           std::vector< FissureBorder > & theFissureBorders )
+  {
+    TIDSortedElemSet::const_iterator nIt = theNodes.begin();
+    const SMDS_MeshNode* n = dynamic_cast< const SMDS_MeshNode*>( *nIt );
+    if ( !n ) return;
+    SMDSAbs_ElementType elemType = SMDSAbs_Volume;
+    if ( n->NbInverseElements( elemType ) == 0 )
+    {
+      elemType = SMDSAbs_Face;
+      if ( n->NbInverseElements( elemType ) == 0 )
+        return;
+    }
+    // unmark elements touching the fissure
+    for ( ; nIt != theNodes.end(); ++nIt )
+      SMESH_MeshAlgos::MarkElems( cast2Node(*nIt)->GetInverseElementIterator(), false );
+
+    // loop on elements touching the fissure to get their borders belonging to the fissure
+    std::set< FissureBorder >              fissureBorders;
+    std::vector< const SMDS_MeshElement* > adjElems;
+    std::vector< const SMDS_MeshNode* >    nodes;
+    SMDS_VolumeTool volTool;
+    for ( nIt = theNodes.begin(); nIt != theNodes.end(); ++nIt )
+    {
+      SMDS_ElemIteratorPtr invIt = cast2Node(*nIt)->GetInverseElementIterator( elemType );
+      while ( invIt->more() )
+      {
+        const SMDS_MeshElement* eInv = invIt->next();
+        if ( eInv->isMarked() ) continue;
+        eInv->setIsMarked( true );
+
+        if ( elemType == SMDSAbs_Volume )
+        {
+          volTool.Set( eInv );
+          int iQuad = eInv->IsQuadratic() ? 2 : 1;
+          for ( int iF = 0, nbF = volTool.NbFaces(); iF < nbF; ++iF )
+          {
+            const SMDS_MeshNode** nn = volTool.GetFaceNodes( iF );
+            int                  nbN = volTool.NbFaceNodes( iF ) / iQuad;
+            nodes.clear();
+            bool allOnFissure = true;
+            for ( int iN = 0; iN < nbN  && allOnFissure; iN += iQuad )
+              if (( allOnFissure = theNodes.count( nn[ iN ])))
+                nodes.push_back( nn[ iN ]);
+            if ( allOnFissure )
+              fissureBorders.insert( std::move( FissureBorder( &nodes[0], nodes.size(),
+                                                               elemType, adjElems )));
+          }
+        }
+        else // elemType == SMDSAbs_Face
+        {
+          const SMDS_MeshNode* nn[2] = { eInv->GetNode( eInv->NbCornerNodes()-1 ), 0 };
+          bool            onFissure0 = theNodes.count( nn[0] ), onFissure1;
+          for ( int iN = 0, nbN = eInv->NbCornerNodes(); iN < nbN; ++iN )
+          {
+            nn[1]      = eInv->GetNode( iN );
+            onFissure1 = theNodes.count( nn[1] );
+            if ( onFissure0 && onFissure1 )
+              fissureBorders.insert( std::move( FissureBorder( nn, 2, elemType, adjElems )));
+            nn[0]      = nn[1];
+            onFissure0 = onFissure1;
+          }
+        }
+      }
+    }
+
+    theFissureBorders.reserve( theFissureBorders.size() + fissureBorders.size());
+    std::set< FissureBorder >::iterator bord = fissureBorders.begin();
+    for ( ; bord != fissureBorders.end(); ++bord )
+    {
+      theFissureBorders.push_back( std::move( const_cast<FissureBorder&>( *bord ) ));
+    }
+    return;
+  } // findFissureBorders()
+
+  //================================================================================
+  /*!
+   * \brief Find elements on one side of a fissure defined by elements or nodes to duplicate
+   *  \param [in] theElemsOrNodes - elements or nodes to duplicate
+   *  \param [in] theNodesNot - nodes not to duplicate
+   *  \param [out] theAffectedElems - the found elements
+   */
+  //================================================================================
+
+  void findAffectedElems( const TIDSortedElemSet& theElemsOrNodes,
+                          TIDSortedElemSet&       theAffectedElems)
+  {
+    if ( theElemsOrNodes.empty() ) return;
+
+    // find FissureBorder's
+
+    std::vector< FissureBorder >           fissure;
+    std::vector< const SMDS_MeshElement* > elemsByFacet;
+
+    TIDSortedElemSet::const_iterator elIt = theElemsOrNodes.begin();
+    if ( (*elIt)->GetType() == SMDSAbs_Node )
+    {
+      findFissureBorders( theElemsOrNodes, fissure );
+    }
+    else
+    {
+      fissure.reserve( theElemsOrNodes.size() );
+      for ( ; elIt != theElemsOrNodes.end(); ++elIt )
+        fissure.push_back( std::move( FissureBorder( *elIt, elemsByFacet )));
+    }
+    if ( fissure.empty() )
+      return;
+
+    // fill borderLinks
+
+    TBorderLinks borderLinks;
+
+    for ( size_t i = 0; i < fissure.size(); ++i )
+    {
+      fissure[i].AddSelfTo( borderLinks );
+    }
+
+    // get theAffectedElems
+
+    // unmark elements having nodes on the fissure, theAffectedElems elements will be marked
+    for ( size_t i = 0; i < fissure.size(); ++i )
+      for ( size_t j = 0; j < fissure[i]._nodes.size(); ++j )
+      {
+        SMESH_MeshAlgos::MarkElemNodes( fissure[i]._nodes[j]->GetInverseElementIterator(),
+                                        false, /*markElem=*/true );
+      }
+
+    std::vector<const SMDS_MeshNode *>                 facetNodes;
+    std::map< const SMDS_MeshNode*, FissureNormal >    fissEdgeNodes2Norm;
+    boost::container::flat_set< const SMDS_MeshNode* > fissureNodes;
+
+    // choose a side of fissure
+    fissure[0].ChooseSide();
+    theAffectedElems.insert( fissure[0].GetMarkedElem() );
+
+    size_t nbCheckedBorders = 0;
+    while ( nbCheckedBorders < fissure.size() )
+    {
+      // find a FissureBorder to treat
+      FissureBorder* bord = 0;
+      for ( size_t i = 0; i < fissure.size()  && !bord; ++i )
+        if ( fissure[i].GetMarkedElem() )
+          bord = & fissure[i];
+      for ( size_t i = 0; i < fissure.size()  && !bord; ++i )
+        if ( fissure[i].NbSub() > 0 && fissure[i]._elems[0] )
+        {
+          bord = & fissure[i];
+          bord->ChooseSide();
+          theAffectedElems.insert( bord->GetMarkedElem() );
+        }
+      if ( !bord ) return;
+      ++nbCheckedBorders;
+
+      // treat FissureBorder's linked to bord
+      fissureNodes.clear();
+      fissureNodes.insert( bord->_nodes.begin(), bord->_nodes.end() );
+      for ( size_t i = 0; i < bord->NbSub(); ++i )
+      {
+        TBorderLinks::iterator l2b = bord->_mappedSubs[ i ];
+        if ( l2b == borderLinks.end() || l2b->second.empty() ) continue;
+        std::vector< FissureBorder* >& linkedBorders = l2b->second;
+        const SubBorder&                          sb = l2b->first;
+        const SMDS_MeshElement*             bordElem = bord->GetMarkedElem();
+
+        if ( linkedBorders.size() == 1 ) // fissure edge reached, fill fissEdgeNodes2Norm
+        {
+          for ( int j = 0; j < sb._nbNodes; ++j )
+            fissEdgeNodes2Norm[ sb._nodes[j] ].Add( sb._nodes[j], *bord );
+          continue;
+        }
+
+        // add to theAffectedElems elems sharing nodes of a SubBorder and a node of bordElem
+        // until an elem adjacent to a neighbour FissureBorder is found
+        facetNodes.clear();
+        facetNodes.insert( facetNodes.end(), sb._nodes, sb._nodes + sb._nbNodes );
+        facetNodes.resize( sb._nbNodes + 1 );
+
+        while ( bordElem )
+        {
+          // check if bordElem is adjacent to a neighbour FissureBorder
+          for ( size_t j = 0; j < linkedBorders.size(); ++j )
+          {
+            FissureBorder* bord2 = linkedBorders[j];
+            if ( bord2 == bord ) continue;
+            if ( bordElem == bord2->_elems[0] || bordElem == bord2->_elems[1] )
+              bordElem = 0;
+            else
+              fissureNodes.insert( bord2->_nodes.begin(), bord2->_nodes.end() );
+          }
+          if ( !bordElem )
+            break;
+
+          // find the next bordElem
+          const SMDS_MeshElement* nextBordElem = 0;
+          for ( int iN = 0, nbN = bordElem->NbCornerNodes(); iN < nbN  && !nextBordElem; ++iN )
+          {
+            const SMDS_MeshNode* n = bordElem->GetNode( iN );
+            if ( fissureNodes.count( n )) continue;
+
+            facetNodes[ sb._nbNodes ] = n;
+            elemsByFacet.clear();
+            if ( SMDS_Mesh::GetElementsByNodes( facetNodes, elemsByFacet ) > 1 )
+            {
+              for ( size_t iE = 0; iE < elemsByFacet.size(); ++iE )
+                if ( elemsByFacet[ iE ] != bordElem &&
+                     !elemsByFacet[ iE ]->isMarked() )
+                {
+                  theAffectedElems.insert( elemsByFacet[ iE ]);
+                  elemsByFacet[ iE ]->setIsMarked( true );
+                  if ( elemsByFacet[ iE ]->GetType() == bordElem->GetType() )
+                    nextBordElem = elemsByFacet[ iE ];
+                }
+            }
+          }
+          bordElem = nextBordElem;
+
+        } // while ( bordElem )
+
+        linkedBorders.clear(); // not to treat this link any more
+
+      } // loop on SubBorder's of a FissureBorder
+
+      bord->Clear();
+
+    } // loop on FissureBorder's
+
+
+    // add elements sharing only one node of the fissure, except those sharing fissure edge nodes
+
+    // mark nodes of theAffectedElems
+    SMESH_MeshAlgos::MarkElemNodes( theAffectedElems.begin(), theAffectedElems.end(), true );
+
+    // unmark nodes of the fissure
+    elIt = theElemsOrNodes.begin();
+    if ( (*elIt)->GetType() == SMDSAbs_Node )
+      SMESH_MeshAlgos::MarkElems( elIt, theElemsOrNodes.end(), false );
+    else
+      SMESH_MeshAlgos::MarkElemNodes( elIt, theElemsOrNodes.end(), false );
+
+    std::vector< gp_XYZ > normVec;
+
+    // loop on nodes of the fissure, add elements having marked nodes
+    for ( elIt = theElemsOrNodes.begin(); elIt != theElemsOrNodes.end(); ++elIt )
+    {
+      const SMDS_MeshElement* e = (*elIt);
+      if ( e->GetType() != SMDSAbs_Node )
+        e->setIsMarked( true ); // avoid adding a fissure element
+
+      for ( int iN = 0, nbN = e->NbCornerNodes(); iN < nbN; ++iN )
+      {
+        const SMDS_MeshNode* n = e->GetNode( iN );
+        if ( fissEdgeNodes2Norm.count( n ))
+          continue;
+
+        SMDS_ElemIteratorPtr invIt = n->GetInverseElementIterator();
+        while ( invIt->more() )
+        {
+          const SMDS_MeshElement* eInv = invIt->next();
+          if ( eInv->isMarked() ) continue;
+          eInv->setIsMarked( true );
+
+          SMDS_ElemIteratorPtr nIt = eInv->nodesIterator();
+          while( nIt->more() )
+            if ( nIt->next()->isMarked())
+            {
+              theAffectedElems.insert( eInv );
+              SMESH_MeshAlgos::MarkElems( eInv->nodesIterator(), true );
+              n->setIsMarked( false );
+              break;
+            }
+        }
+      }
+    }
+
+    // add elements on the fissure edge
+    std::map< const SMDS_MeshNode*, FissureNormal >::iterator n2N;
+    for ( n2N = fissEdgeNodes2Norm.begin(); n2N != fissEdgeNodes2Norm.end(); ++n2N )
+    {
+      const SMDS_MeshNode* edgeNode = n2N->first;
+      const FissureNormal & normals = n2N->second;
+
+      SMDS_ElemIteratorPtr invIt = edgeNode->GetInverseElementIterator();
+      while ( invIt->more() )
+      {
+        const SMDS_MeshElement* eInv = invIt->next();
+        if ( eInv->isMarked() ) continue;
+        eInv->setIsMarked( true );
+
+        // classify eInv using normals
+        bool toAdd = normals.IsIn( edgeNode, eInv );
+        if ( toAdd ) // check if all nodes lie on the fissure edge
+        {
+          bool notOnEdge = false;
+          for ( int iN = 0, nbN = eInv->NbCornerNodes(); iN < nbN  && !notOnEdge; ++iN )
+            notOnEdge = !fissEdgeNodes2Norm.count( eInv->GetNode( iN ));
+          toAdd = notOnEdge;
+        }
+        if ( toAdd )
+        {
+          theAffectedElems.insert( eInv );
+        }
+      }
+    }
+
+    return;
+  } // findAffectedElems()
+} // namespace
+
 //================================================================================
 /*!
  * \brief Create elements equal (on same nodes) to given ones
@@ -10601,7 +10907,6 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
 
   SMDSAbs_ElementType type = SMDSAbs_All;
   SMDS_ElemIteratorPtr elemIt;
-  vector< const SMDS_MeshElement* > allElems;
   if ( theElements.empty() )
   {
     if ( mesh->NbNodes() == 0 )
@@ -10615,21 +10920,19 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
       if ( mesh->GetMeshInfo().NbElements( types[i] ))
       {
         type = types[i];
+        elemIt = mesh->elementsIterator( type );
         break;
       }
-    // put all elements in the vector <allElems>
-    allElems.reserve( mesh->GetMeshInfo().NbElements( type ));
-    elemIt = mesh->elementsIterator( type );
-    while ( elemIt->more() )
-      allElems.push_back( elemIt->next());
-    elemIt = elemSetIterator( allElems );
   }
   else
   {
     type = (*theElements.begin())->GetType();
-    elemIt = elemSetIterator( theElements );
+    elemIt = SMESHUtils::elemSetIterator( theElements );
   }
 
+  // un-mark all elements to avoid duplicating just created elements
+  SMESH_MeshAlgos::MarkElems( mesh->elementsIterator( type ), false );
+
   // duplicate elements
 
   ElemFeatures elemType;
@@ -10638,13 +10941,14 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
   while ( elemIt->more() )
   {
     const SMDS_MeshElement* elem = elemIt->next();
-    if ( elem->GetType() != type )
+    if ( elem->GetType() != type || elem->isMarked() )
       continue;
 
     elemType.Init( elem, /*basicOnly=*/false );
     nodes.assign( elem->begin_nodes(), elem->end_nodes() );
 
-    AddElement( nodes, elemType );
+    if ( const SMDS_MeshElement* newElem = AddElement( nodes, elemType ))
+      newElem->setIsMarked( true );
   }
 }
 
@@ -10664,8 +10968,7 @@ bool SMESH_MeshEditor::DoubleNodes( const TIDSortedElemSet& theElems,
                                     const TIDSortedElemSet& theNodesNot,
                                     const TIDSortedElemSet& theAffectedElems )
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( theElems.size() == 0 )
     return false;
@@ -10710,8 +11013,8 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh*           theMeshDS,
   for ( ;  elemItr != theElems.end(); ++elemItr )
   {
     const SMDS_MeshElement* anElem = *elemItr;
-    if (!anElem)
-      continue;
+    // if (!anElem)
+    //   continue;
 
     // duplicate nodes to duplicate element
     bool isDuplicate = false;
@@ -10733,7 +11036,7 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh*           theMeshDS,
         aNewNode = theMeshDS->AddNode( aCurrNode->X(), aCurrNode->Y(), aCurrNode->Z() );
         copyPosition( aCurrNode, aNewNode );
         theNodeNodeMap[ aCurrNode ] = aNewNode;
-        myLastCreatedNodes.Append( aNewNode );
+        myLastCreatedNodes.push_back( aNewNode );
       }
       isDuplicate |= (aCurrNode != aNewNode);
       newNodes[ ind++ ] = aNewNode;
@@ -10765,8 +11068,7 @@ bool SMESH_MeshEditor::doubleNodes(SMESHDS_Mesh*           theMeshDS,
 bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
                                     const std::list< int >& theListOfModifiedElems )
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( theListOfNodes.size() == 0 )
     return false;
@@ -10782,8 +11084,7 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
   std::list< int >::const_iterator aNodeIter;
   for ( aNodeIter = theListOfNodes.begin(); aNodeIter != theListOfNodes.end(); ++aNodeIter )
   {
-    int aCurr = *aNodeIter;
-    SMDS_MeshNode* aNode = (SMDS_MeshNode*)aMeshDS->FindNode( aCurr );
+    const SMDS_MeshNode* aNode = aMeshDS->FindNode( *aNodeIter );
     if ( !aNode )
       continue;
 
@@ -10794,53 +11095,32 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
     {
       copyPosition( aNode, aNewNode );
       anOldNodeToNewNode[ aNode ] = aNewNode;
-      myLastCreatedNodes.Append( aNewNode );
+      myLastCreatedNodes.push_back( aNewNode );
     }
   }
 
-  // Create map of new nodes for modified elements
+  // Change nodes of elements
 
-  std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> > anElemToNodes;
+  std::vector<const SMDS_MeshNode*> aNodeArr;
 
   std::list< int >::const_iterator anElemIter;
-  for ( anElemIter = theListOfModifiedElems.begin();
-        anElemIter != theListOfModifiedElems.end(); ++anElemIter )
+  for ( anElemIter =  theListOfModifiedElems.begin();
+        anElemIter != theListOfModifiedElems.end();
+        anElemIter++ )
   {
-    int aCurr = *anElemIter;
-    SMDS_MeshElement* anElem = (SMDS_MeshElement*)aMeshDS->FindElement( aCurr );
+    const SMDS_MeshElement* anElem = aMeshDS->FindElement( *anElemIter );
     if ( !anElem )
       continue;
 
-    vector<const SMDS_MeshNode*> aNodeArr( anElem->NbNodes() );
-
-    SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
-    int ind = 0;
-    while ( anIter->more() )
-    {
-      SMDS_MeshNode* aCurrNode = (SMDS_MeshNode*)anIter->next();
-      if ( aCurr && anOldNodeToNewNode.find( aCurrNode ) != anOldNodeToNewNode.end() )
-      {
-        const SMDS_MeshNode* aNewNode = anOldNodeToNewNode[ aCurrNode ];
-        aNodeArr[ ind++ ] = aNewNode;
-      }
-      else
-        aNodeArr[ ind++ ] = aCurrNode;
-    }
-    anElemToNodes[ anElem ] = aNodeArr;
-  }
-
-  // Change nodes of elements
-
-  std::map< SMDS_MeshElement*, vector<const SMDS_MeshNode*> >::iterator
-    anElemToNodesIter = anElemToNodes.begin();
-  for ( ; anElemToNodesIter != anElemToNodes.end(); ++anElemToNodesIter )
-  {
-    const SMDS_MeshElement* anElem = anElemToNodesIter->first;
-    vector<const SMDS_MeshNode*> aNodeArr = anElemToNodesIter->second;
-    if ( anElem )
+    aNodeArr.assign( anElem->begin_nodes(), anElem->end_nodes() );
+    for( size_t i = 0; i < aNodeArr.size(); ++i )
     {
-      aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], anElem->NbNodes() );
+      std::map< const SMDS_MeshNode*, const SMDS_MeshNode* >::iterator n2n =
+        anOldNodeToNewNode.find( aNodeArr[ i ]);
+      if ( n2n != anOldNodeToNewNode.end() )
+        aNodeArr[ i ] = n2n->second;
     }
+    aMeshDS->ChangeElementNodes( anElem, &aNodeArr[ 0 ], aNodeArr.size() );
   }
 
   return true;
@@ -10850,8 +11130,8 @@ namespace {
 
   //================================================================================
   /*!
-  \brief Check if element located inside shape
-  \return TRUE if IN or ON shape, FALSE otherwise
+    \brief Check if element located inside shape
+    \return TRUE if IN or ON shape, FALSE otherwise
   */
   //================================================================================
 
@@ -10861,9 +11141,8 @@ namespace {
                 const double            theTol)
   {
     gp_XYZ centerXYZ (0, 0, 0);
-    SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
-    while (aNodeItr->more())
-      centerXYZ += SMESH_TNodeXYZ(cast2Node( aNodeItr->next()));
+    for ( SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); aNodeItr->more(); )
+      centerXYZ += SMESH_NodeXYZ( aNodeItr->next() );
 
     gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
     theClassifier.Perform(aPnt, theTol);
@@ -10918,9 +11197,9 @@ namespace {
          (select elements with a gravity center on the side given by faces normals).
          This mode (null shape) is faster, but works only when theElems are faces, with coherents orientations.
          The replicated nodes should be associated to affected elements.
-  \return groups of affected elements
+  \return true
   \sa DoubleNodeElemGroupsInRegion()
- */
+*/
 //================================================================================
 
 bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theElems,
@@ -10930,94 +11209,7 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
 {
   if ( theShape.IsNull() )
   {
-    std::set<const SMDS_MeshNode*> alreadyCheckedNodes;
-    std::set<const SMDS_MeshElement*> alreadyCheckedElems;
-    std::set<const SMDS_MeshElement*> edgesToCheck;
-    alreadyCheckedNodes.clear();
-    alreadyCheckedElems.clear();
-    edgesToCheck.clear();
-
-    // --- iterates on elements to be replicated and get elements by back references from their nodes
-
-    TIDSortedElemSet::const_iterator elemItr = theElems.begin();
-    for ( ;  elemItr != theElems.end(); ++elemItr )
-    {
-      SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
-      if (!anElem || (anElem->GetType() != SMDSAbs_Face))
-        continue;
-      gp_XYZ normal;
-      SMESH_MeshAlgos::FaceNormal( anElem, normal, /*normalized=*/true );
-      std::set<const SMDS_MeshNode*> nodesElem;
-      nodesElem.clear();
-      SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
-      while ( nodeItr->more() )
-      {
-        const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
-        nodesElem.insert(aNode);
-      }
-      std::set<const SMDS_MeshNode*>::iterator nodit = nodesElem.begin();
-      for (; nodit != nodesElem.end(); nodit++)
-      {
-        const SMDS_MeshNode* aNode = *nodit;
-        if ( !aNode || theNodesNot.find(aNode) != theNodesNot.end() )
-          continue;
-        if (alreadyCheckedNodes.find(aNode) != alreadyCheckedNodes.end())
-          continue;
-        alreadyCheckedNodes.insert(aNode);
-        SMDS_ElemIteratorPtr backElemItr = aNode->GetInverseElementIterator();
-        while ( backElemItr->more() )
-        {
-          const SMDS_MeshElement* curElem = backElemItr->next();
-          if (alreadyCheckedElems.find(curElem) != alreadyCheckedElems.end())
-            continue;
-          if (theElems.find(curElem) != theElems.end())
-            continue;
-          alreadyCheckedElems.insert(curElem);
-          double x=0, y=0, z=0;
-          int nb = 0;
-          SMDS_ElemIteratorPtr nodeItr2 = curElem->nodesIterator();
-          while ( nodeItr2->more() )
-          {
-            const SMDS_MeshNode* anotherNode = cast2Node(nodeItr2->next());
-            x += anotherNode->X();
-            y += anotherNode->Y();
-            z += anotherNode->Z();
-            nb++;
-          }
-          gp_XYZ p;
-          p.SetCoord( x/nb -aNode->X(),
-                      y/nb -aNode->Y(),
-                      z/nb -aNode->Z() );
-          if (normal*p > 0)
-          {
-            theAffectedElems.insert( curElem );
-          }
-          else if (curElem->GetType() == SMDSAbs_Edge)
-            edgesToCheck.insert(curElem);
-        }
-      }
-    }
-    // --- add also edges lying on the set of faces (all nodes in alreadyCheckedNodes)
-    std::set<const SMDS_MeshElement*>::iterator eit = edgesToCheck.begin();
-    for( ; eit != edgesToCheck.end(); eit++)
-    {
-      bool onside = true;
-      const SMDS_MeshElement* anEdge = *eit;
-      SMDS_ElemIteratorPtr nodeItr = anEdge->nodesIterator();
-      while ( nodeItr->more() )
-      {
-        const SMDS_MeshNode* aNode = cast2Node(nodeItr->next());
-        if (alreadyCheckedNodes.find(aNode) == alreadyCheckedNodes.end())
-        {
-          onside = false;
-          break;
-        }
-      }
-      if (onside)
-      {
-        theAffectedElems.insert(anEdge);
-      }
-    }
+    findAffectedElems( theElems, theAffectedElems );
   }
   else
   {
@@ -11038,9 +11230,7 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
     TIDSortedElemSet::const_iterator elemItr = theElems.begin();
     for ( ;  elemItr != theElems.end(); ++elemItr )
     {
-      SMDS_MeshElement* anElem = (SMDS_MeshElement*)*elemItr;
-      if (!anElem)
-        continue;
+      SMDS_MeshElement*     anElem = (SMDS_MeshElement*)*elemItr;
       SMDS_ElemIteratorPtr nodeItr = anElem->nodesIterator();
       while ( nodeItr->more() )
       {
@@ -11052,9 +11242,9 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
         {
           const SMDS_MeshElement* curElem = backElemItr->next();
           if ( curElem && theElems.find(curElem) == theElems.end() &&
-              ( bsc3d.get() ?
-                isInside( curElem, *bsc3d, aTol ) :
-                isInside( curElem, *aFaceClassifier, aTol )))
+               ( bsc3d.get() ?
+                 isInside( curElem, *bsc3d, aTol ) :
+                 isInside( curElem, *aFaceClassifier, aTol )))
             theAffectedElems.insert( curElem );
         }
       }
@@ -11176,7 +11366,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
   meshDS->BuildDownWardConnectivity(true);
   CHRONO(50);
-  SMDS_UnstructuredGrid *grid = meshDS->getGrid();
+  SMDS_UnstructuredGrid *grid = meshDS->GetGrid();
 
   // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
   //     build the list of cells with only a node or an edge on the border, with their domain and volume indexes
@@ -11242,7 +11432,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       const SMDS_MeshElement* anElem = *elemItr;
       if (!anElem)
         continue;
-      int vtkId = anElem->getVtkId();
+      int vtkId = anElem->GetVtkID();
       //MESSAGE("  vtkId " << vtkId << " smdsId " << anElem->GetID());
       int neighborsVtkIds[NBMAXNEIGHBORS];
       int downIds[NBMAXNEIGHBORS];
@@ -11250,7 +11440,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
       for (int n = 0; n < nbNeighbors; n++)
       {
-        int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+        int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
         const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
         if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared
         {
@@ -11313,7 +11503,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         for (int i=0; i<l.ncells; i++)
         {
           int vtkId = l.cells[i];
-          const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
+          const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->FromVtkToSmds(vtkId));
           if (!domain.count(anElem))
             continue;
           int vtkType = grid->GetCellType(vtkId);
@@ -11397,7 +11587,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             double *coords = grid->GetPoint(oldId);
             SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
             copyPosition( meshDS->FindNodeVtk( oldId ), newNode );
-            int newId = newNode->getVtkId();
+            int newId = newNode->GetVtkID();
             nodeDomains[oldId][idom] = newId; // cloned node for other domains
             //MESSAGE("-+-+-c     oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" <<nodeDomains[oldId].size());
           }
@@ -11470,7 +11660,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                 gp_Pnt p1(coords[0], coords[1], coords[2]);
                 gp_Pnt gref;
                 int vtkVolIds[1000];  // an edge can belong to a lot of volumes
-                map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
+                map<int, SMDS_MeshVolume*> domvol; // domain --> a volume with the edge
                 map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
                 int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
                 for ( size_t id = 0; id < doms.size(); id++ )
@@ -11479,26 +11669,31 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                   const TIDSortedElemSet& domain = (idom == iRestDom) ? theRestDomElems : theElems[idom];
                   for ( int ivol = 0; ivol < nbvol; ivol++ )
                   {
-                    int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
-                    SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
+                    int smdsId = meshDS->FromVtkToSmds(vtkVolIds[ivol]);
+                    const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
                     if (domain.count(elem))
                     {
-                      SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
-                      domvol[idom] = svol;
+                      const SMDS_MeshVolume* svol = SMDS_Mesh::DownCast<SMDS_MeshVolume>(elem);
+                      domvol[idom] = (SMDS_MeshVolume*) svol;
                       //MESSAGE("  domain " << idom << " volume " << elem->GetID());
-                      double values[3];
+                      double values[3] = { 0,0,0 };
                       vtkIdType npts = 0;
                       vtkIdType* pts = 0;
                       grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
-                      SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
-                      if (id ==0)
+                      for ( vtkIdType i = 0; i < npts; ++i )
+                      {
+                        double *coords = grid->GetPoint( pts[i] );
+                        for ( int j = 0; j < 3; ++j )
+                          values[j] += coords[j] / npts;
+                      }
+                      if ( id == 0 )
                       {
-                        gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+                        gref.SetCoord( values[0], values[1], values[2] );
                         angleDom[idom] = 0;
                       }
                       else
                       {
-                        gp_Pnt g(values[0], values[1], values[2]);
+                        gp_Pnt g( values[0], values[1], values[2] );
                         angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
                         //MESSAGE("  angle=" << angleDom[idom]);
                       }
@@ -11687,7 +11882,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               feDom[vtkId] = idomain;
               faceOrEdgeDom[aCell] = emptyMap;
               faceOrEdgeDom[aCell][idomain] = vtkId; // affect face or edge to the first domain only
-              //MESSAGE("affect cell " << this->GetMeshDS()->fromVtkToSmds(vtkId) << " domain " << idomain
+              //MESSAGE("affect cell " << this->GetMeshDS()->FromVtkToSmds(vtkId) << " domain " << idomain
               //        << " type " << vtkType << " downId " << downId);
             }
       }
@@ -11719,7 +11914,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       {
         int idom = itdom->first;
         int vtkVolId = itdom->second;
-        //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom);
+        //MESSAGE("modify nodes of cell " << this->GetMeshDS()->FromVtkToSmds(vtkVolId) << " domain " << idom);
         localClonedNodeIds.clear();
         for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
         {
@@ -11786,8 +11981,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
     TIDSortedElemSet::const_iterator elemItr = domain.begin();
     for ( ; elemItr != domain.end(); ++elemItr )
     {
-      SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
-      SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
+      const SMDS_MeshFace* aFace = meshDS->DownCast<SMDS_MeshFace> ( *elemItr );
       if (!aFace)
         continue;
       // MESSAGE("aFace=" << aFace->GetID());
@@ -11796,11 +11990,11 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
 
       // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
 
-      SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+      SMDS_NodeIteratorPtr nodeIt = aFace->nodeIterator();
       while (nodeIt->more())
       {
-        const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
-        bool isMedium = isQuad && (aFace->IsMediumNode(node));
+        const SMDS_MeshNode* node = nodeIt->next();
+        bool isMedium = ( isQuad && aFace->IsMediumNode( node ));
         if (isMedium)
           ln2.push_back(node);
         else
@@ -11908,7 +12102,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
 
       // --- modify the face
 
-      aFace->ChangeNodes(&ln[0], ln.size());
+      const_cast<SMDS_MeshFace*>( aFace )->ChangeNodes( &ln[0], ln.size() );
     }
   }
   return true;
@@ -12019,7 +12213,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
   meshDS->BuildDownWardConnectivity(true);
-  SMDS_UnstructuredGrid* grid = meshDS->getGrid();
+  SMDS_UnstructuredGrid* grid = meshDS->GetGrid();
 
   // --- set of volumes detected inside
 
@@ -12046,7 +12240,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       while (volItr->more())
       {
         vol = (SMDS_MeshElement*)volItr->next();
-        setOfInsideVol.insert(vol->getVtkId());
+        setOfInsideVol.insert(vol->GetVtkID());
         sgrp->Add(vol->GetID());
       }
     }
@@ -12101,7 +12295,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     while (volItr->more())
     {
       startVol = (SMDS_MeshElement*)volItr->next();
-      setOfVolToCheck.insert(startVol->getVtkId());
+      setOfVolToCheck.insert(startVol->GetVtkID());
     }
     if (setOfVolToCheck.empty())
     {
@@ -12120,7 +12314,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     {
       std::set<int>::iterator it = setOfVolToCheck.begin();
       int vtkId = *it;
-      //MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+      //MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
       bool volInside = false;
       vtkIdType npts = 0;
       vtkIdType* pts = 0;
@@ -12154,14 +12348,14 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         if (distance2 < radius2)
         {
           volInside = true; // one or more nodes inside the domain
-          sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+          sgrp->Add(meshDS->FromVtkToSmds(vtkId));
           break;
         }
       }
       if (volInside)
       {
         setOfInsideVol.insert(vtkId);
-        //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
         unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12173,7 +12367,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       else
       {
         setOfOutsideVol.insert(vtkId);
-        //MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
       }
       setOfVolToCheck.erase(vtkId);
     }
@@ -12208,7 +12402,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       int vtkId = *it;
       if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON)
       {
-        //MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
         int countInside = 0;
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
@@ -12220,9 +12414,9 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         //MESSAGE("countInside " << countInside);
         if (countInside > 1)
         {
-          //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+          //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
           setOfInsideVol.insert(vtkId);
-          sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+          sgrp->Add(meshDS->FromVtkToSmds(vtkId));
           addedInside = true;
         }
         else
@@ -12243,7 +12437,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   for (; it != setOfInsideVol.end(); ++it)
   {
     int vtkId = *it;
-    //MESSAGE("  vtkId " << vtkId  << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+    //MESSAGE("  vtkId " << vtkId  << " smdsId " << meshDS->FromVtkToSmds(vtkId));
     int neighborsVtkIds[NBMAXNEIGHBORS];
     int downIds[NBMAXNEIGHBORS];
     unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12262,7 +12456,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
         if (vtkFaceId >= 0)
         {
-          sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId));
+          sgrpi->Add(meshDS->FromVtkToSmds(vtkFaceId));
           // find also the smds edges on this face
           int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]);
           const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]);
@@ -12271,7 +12465,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
           {
             int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]);
             if (vtkEdgeId >= 0)
-              sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId));
+              sgrpei->Add(meshDS->FromVtkToSmds(vtkEdgeId));
           }
         }
       }
@@ -12281,7 +12475,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         skinFaces[face] = vtkId;
         int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
         if (vtkFaceId >= 0)
-          sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId));
+          sgrps->Add(meshDS->FromVtkToSmds(vtkFaceId));
       }
     }
   }
@@ -12300,7 +12494,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   {
     const SMDS_MeshElement *elem = itelem->next();
     int shapeId = elem->getshapeId();
-    int vtkId = elem->getVtkId();
+    int   vtkId = elem->GetVtkID();
     if (!shapeIdToVtkIdSet.count(shapeId))
     {
       shapeIdToVtkIdSet[shapeId] = emptySet;
@@ -12335,7 +12529,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       {
         if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here
           continue;
-        int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+        int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
         const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
         if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group
         {
@@ -12573,9 +12767,9 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
 
   SMDS_ElemIteratorPtr eIt;
   if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
-  else                  eIt = elemSetIterator( elements );
+  else                  eIt = SMESHUtils::elemSetIterator( elements );
 
-  while (eIt->more())
+  while ( eIt->more() )
   {
     const SMDS_MeshElement* elem = eIt->next();
     const int              iQuad = elem->IsQuadratic();
@@ -12656,7 +12850,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     else if ( elem->GetType() == SMDSAbs_Face ) // elem is a face ------------------------
     {
       avoidSet.clear(), avoidSet.insert( elem );
-      elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesElemIterator() ),
+      elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesIterator() ),
                         SMDS_MeshElement::iterator() );
       elemNodes.push_back( elemNodes[0] );
       nodes.resize( 2 + iQuad );
@@ -12752,7 +12946,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     else // store present elements to add them to a group
       for ( size_t i = 0 ; i < presentBndElems.size(); ++i )
       {
-        presentEditor->myLastCreatedElems.Append( presentBndElems[ i ]);
+        presentEditor->myLastCreatedElems.push_back( presentBndElems[ i ]);
       }
 
   } // loop on given elements
@@ -12763,11 +12957,11 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   if ( group )
   {
     if ( SMESHDS_Group* g = dynamic_cast<SMESHDS_Group*>( group->GetGroupDS() ))
-      for ( int i = 0; i < tgtEditor.myLastCreatedElems.Size(); ++i )
-        g->SMDSGroup().Add( tgtEditor.myLastCreatedElems( i+1 ));
+      for ( size_t i = 0; i < tgtEditor.myLastCreatedElems.size(); ++i )
+        g->SMDSGroup().Add( tgtEditor.myLastCreatedElems[ i ]);
   }
-  tgtEditor.myLastCreatedElems.Clear();
-  tgtEditor2.myLastCreatedElems.Clear();
+  tgtEditor.myLastCreatedElems.clear();
+  tgtEditor2.myLastCreatedElems.clear();
 
   // -----------------------
   // 5. Copy given elements
@@ -12775,7 +12969,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   if ( toCopyElements && targetMesh != myMesh )
   {
     if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
-    else                  eIt = elemSetIterator( elements );
+    else                  eIt = SMESHUtils::elemSetIterator( elements );
     while (eIt->more())
     {
       const SMDS_MeshElement* elem = eIt->next();
@@ -12784,7 +12978,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
         tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, elem->GetNode(inode) );
       tgtEditor.AddElement( tgtNodes, elemToCopy.Init( elem ));
 
-      tgtEditor.myLastCreatedElems.Clear();
+      tgtEditor.myLastCreatedElems.clear();
     }
   }
   return nbAddedBnd;
@@ -12810,7 +13004,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
 
   case SMDS_TOP_FACE:
   {
-    const SMDS_FacePosition* fPos = static_cast< const SMDS_FacePosition* >( pos );
+    SMDS_FacePositionPtr fPos = pos;
     GetMeshDS()->SetNodeOnFace( to, from->getshapeId(),
                                 fPos->GetUParameter(), fPos->GetVParameter() );
     break;
@@ -12818,7 +13012,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   case SMDS_TOP_EDGE:
   {
     // WARNING: it is dangerous to set equal nodes on one EDGE!!!!!!!!
-    const SMDS_EdgePosition* ePos = static_cast< const SMDS_EdgePosition* >( pos );
+    SMDS_EdgePositionPtr ePos = pos;
     GetMeshDS()->SetNodeOnEdge( to, from->getshapeId(), ePos->GetUParameter() );
     break;
   }
@@ -12831,3 +13025,482 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   default:;
   }
 }
+
+namespace // utils for MakePolyLine
+{
+  //================================================================================
+  /*!
+   * \brief Sequence of found points and a current point data
+   */
+  struct Path
+  {
+    std::vector< gp_XYZ >   myPoints;
+    double                  myLength;
+
+    int                     mySrcPntInd; //!< start point index
+    const SMDS_MeshElement* myFace;
+    SMESH_NodeXYZ           myNode1;
+    SMESH_NodeXYZ           myNode2;
+    int                     myNodeInd1;
+    int                     myNodeInd2;
+    double                  myDot1;
+    double                  myDot2;
+    TIDSortedElemSet        myElemSet, myAvoidSet;
+
+    Path(): myLength(0.0), myFace(0) {}
+
+    bool SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                         const SMDS_MeshElement* face,
+                         const gp_XYZ&           plnNorm,
+                         const gp_XYZ&           plnOrig );
+
+    void AddPoint( const gp_XYZ& p );
+
+    bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig );
+
+    bool ReachSamePoint( const Path& other );
+
+    static void Remove( std::vector< Path > & paths, size_t& i );
+  };
+
+  //================================================================================
+  /*!
+   * \brief Return true if this Path meats another
+   */
+  //================================================================================
+
+  bool Path::ReachSamePoint( const Path& other )
+  {
+    return ( mySrcPntInd != other.mySrcPntInd &&
+             myFace == other.myFace );
+  }
+
+  //================================================================================
+  /*!
+   * \brief Remove a path from a vector
+   */
+  //================================================================================
+
+  void Path::Remove( std::vector< Path > & paths, size_t& i )
+  {
+    if ( paths.size() > 1 )
+    {
+      size_t j = paths.size() - 1; // last item to be removed
+      if ( i < j )
+      {
+        paths[ i ].myPoints.swap( paths[ j ].myPoints );
+        paths[ i ].myLength    = paths[ j ].myLength;
+        paths[ i ].mySrcPntInd = paths[ j ].mySrcPntInd;
+        paths[ i ].myFace      = paths[ j ].myFace;
+        paths[ i ].myNode1     = paths[ j ].myNode1;
+        paths[ i ].myNode2     = paths[ j ].myNode2;
+        paths[ i ].myNodeInd1  = paths[ j ].myNodeInd1;
+        paths[ i ].myNodeInd2  = paths[ j ].myNodeInd2;
+        paths[ i ].myDot1      = paths[ j ].myDot1;
+        paths[ i ].myDot2      = paths[ j ].myDot2;
+      }
+    }
+    paths.pop_back();
+    if ( i > 0 )
+      --i;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point that is at a node of a face if the face is intersected by plane.
+   *        Return false if the node is a sole intersection point of the face and the plane
+   */
+  //================================================================================
+
+  bool Path::SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                             const SMDS_MeshElement* face,
+                             const gp_XYZ&           plnNorm,
+                             const gp_XYZ&           plnOrig )
+  {
+    if ( face == myFace )
+      return false;
+    myNodeInd1 = face->GetNodeIndex( cornerNode._node );
+    myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes();
+    int   ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes();
+    myNode1.Set( face->GetNode( ind3 ));
+    myNode2.Set( face->GetNode( myNodeInd2 ));
+
+    myDot1 = plnNorm * ( myNode1 - plnOrig );
+    myDot2 = plnNorm * ( myNode2 - plnOrig );
+
+    bool ok = ( myDot1 * myDot2 < 0 );
+    if ( !ok && myDot1 * myDot2 == 0 )
+    {
+      ok = ( myDot1 != myDot2 );
+      if ( ok && myFace )
+        ok = ( myFace->GetNodeIndex(( myDot1 == 0 ? myNode1 : myNode2 )._node ) < 0 );
+    }
+    if ( ok )
+    {
+      myFace = face;
+      myDot1 = 0;
+      AddPoint( cornerNode );
+    }
+    return ok;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point and update myLength
+   */
+  //================================================================================
+
+  void Path::AddPoint( const gp_XYZ& p )
+  {
+    if ( !myPoints.empty() )
+      myLength += ( p - myPoints.back() ).Modulus();
+    else
+      myLength = 0;
+    myPoints.push_back( p );
+  }
+
+  //================================================================================
+  /*!
+   * \brief Try to find the next point
+   *  \param [in] plnNorm - cutting plane normal
+   *  \param [in] plnOrig - cutting plane origin
+   */
+  //================================================================================
+
+  bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig )
+  {
+    int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes();
+    if ( myNodeInd2 == nodeInd3 )
+      nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes();
+
+    SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 );
+    double         dot3 = plnNorm * ( node3 - plnOrig );
+
+    if ( dot3 * myDot1 < 0. )
+    {
+      myNode2    = node3;
+      myNodeInd2 = nodeInd3;
+      myDot2     = dot3;
+    }
+    else if ( dot3 * myDot2 < 0. )
+    {
+      myNode1    = node3;
+      myNodeInd1 = nodeInd3;
+      myDot1     = dot3;
+    }
+    else if ( dot3 == 0. )
+    {
+      SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+    else if ( myDot2 == 0. )
+    {
+      SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner()
+      SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+
+    double r = Abs( myDot1 / ( myDot2 - myDot1 ));
+    AddPoint( myNode1 * ( 1 - r ) + myNode2 * r );
+
+    myAvoidSet.clear();
+    myAvoidSet.insert( myFace );
+    myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node,
+                                             myElemSet,   myAvoidSet,
+                                             &myNodeInd1, &myNodeInd2 );
+    return myFace;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Compute a path between two points of PolySegment
+   */
+  struct PolyPathCompute
+  {
+    SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's
+    std::vector< Path >&                   myPaths;    //!< path of each of segments to compute
+    SMESH_Mesh*                            myMesh;
+    mutable std::vector< std::string >     myErrors;
+
+    PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments,
+                     std::vector< Path >&                   thePaths,
+                     SMESH_Mesh*                            theMesh):
+      mySegments( theSegments ),
+      myPaths( thePaths ),
+      myMesh( theMesh ),
+      myErrors( theSegments.size() )
+    {
+    }
+#undef SMESH_CAUGHT
+#define SMESH_CAUGHT myErrors[i] =
+    void operator() ( const int i ) const
+    {
+      SMESH_TRY;
+      const_cast< PolyPathCompute* >( this )->Compute( i );
+      SMESH_CATCH( SMESH::returnError );
+    }
+#undef SMESH_CAUGHT
+    //================================================================================
+    /*!
+     * \brief Compute a path of a given segment
+     */
+    //================================================================================
+
+    void Compute( const int iSeg )
+    {
+      SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
+
+      // get a cutting plane
+
+      gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+      gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+      if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+      if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+      gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+      gp_XYZ plnOrig = p2;
+
+      // find paths connecting the 2 end points of polySeg
+
+      std::vector< Path > paths; paths.reserve(10);
+
+      // initialize paths
+
+      for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
+      {
+        Path path;
+        path.mySrcPntInd = iP;
+        size_t nbPaths = paths.size();
+
+        if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
+        {
+          while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
+                                                                 polySeg.myNode2[ iP ],
+                                                                 path.myElemSet,
+                                                                 path.myAvoidSet,
+                                                                 &path.myNodeInd1,
+                                                                 &path.myNodeInd2 )))
+          {
+            path.myNode1.Set( polySeg.myNode1[ iP ]);
+            path.myNode2.Set( polySeg.myNode2[ iP ]);
+            path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
+            path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
+            path.myPoints.clear();
+            path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
+            path.myAvoidSet.insert( path.myFace );
+            paths.push_back( path );
+          }
+          if ( nbPaths == paths.size() )
+            throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
+                                     << " in a PolySegment " << iSeg );
+        }
+        else // an end point is at node
+        {
+          std::set<const SMDS_MeshNode* > nodes;
+          SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
+          while ( fIt->more() )
+          {
+            path.myPoints.clear();
+            if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig ))
+            {
+              if (( path.myDot1 * path.myDot2 != 0 ) ||
+                  ( nodes.insert( path.myDot1 == 0 ? path.myNode1._node : path.myNode2._node ).second ))
+                paths.push_back( path );
+            }
+          }
+        }
+
+        // look for a one-segment path
+        for ( size_t i = 0; i < nbPaths; ++i )
+          for ( size_t j = nbPaths; j < paths.size(); ++j )
+            if ( paths[i].myFace == paths[j].myFace )
+            {
+              myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] );
+              myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] );
+              paths.clear();
+            }
+      }
+
+      // extend paths
+
+      myPaths[ iSeg ].myLength = 1e100;
+
+      while ( paths.size() >= 2 )
+      {
+        for ( size_t i = 0; i < paths.size(); ++i )
+        {
+          Path& path = paths[ i ];
+          if ( !path.Extend( plnNorm, plnOrig ) ||         // path reached a mesh boundary
+               path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
+          {
+            Path::Remove( paths, i );
+            continue;
+          }
+
+          // join paths that reach same point
+          for ( size_t j = 0; j < paths.size(); ++j )
+          {
+            if ( i != j && paths[i].ReachSamePoint( paths[j] ))
+            {
+              double   distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus();
+              double fullLength = ( paths[i].myLength + paths[j].myLength + distLast );
+              if ( fullLength < myPaths[ iSeg ].myLength )
+              {
+                myPaths[ iSeg ].myLength = fullLength;
+                std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints;
+                allPoints.swap( paths[i].myPoints );
+                allPoints.insert( allPoints.end(),
+                                  paths[j].myPoints.rbegin(),
+                                  paths[j].myPoints.rend() );
+              }
+              Path::Remove( paths, i );
+              Path::Remove( paths, j );
+            }
+          }
+        }
+        if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() )
+          throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()"));
+      }
+
+      if ( myPaths[ iSeg ].myPoints.empty() )
+        throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg );
+
+    } // PolyPathCompute::Compute()
+
+  }; // struct PolyPathCompute
+
+} // namespace
+
+//=======================================================================
+//function : MakePolyLine
+//purpose  : Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+//           the initial mesh
+//=======================================================================
+
+void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments&   theSegments,
+                                     SMESHDS_Group*         theGroup,
+                                     SMESH_ElementSearcher* theSearcher)
+{
+  std::vector< Path > segPaths( theSegments.size() ); // path of each of segments
+
+  SMESH_ElementSearcher* searcher = theSearcher;
+  SMESHUtils::Deleter<SMESH_ElementSearcher> delSearcher;
+  if ( !searcher )
+  {
+    searcher = SMESH_MeshAlgos::GetElementSearcher( *GetMeshDS() );
+    delSearcher._obj = searcher;
+  }
+
+  // get cutting planes
+
+  std::vector< bool > isVectorOK( theSegments.size(), true );
+  const double planarCoef = 0.333; // plane height in planar case
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    PolySegment& polySeg = theSegments[ iSeg ];
+
+    gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+    gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+    if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+    if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+    gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+
+    isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
+    if ( !isVectorOK[ iSeg ])
+    {
+      gp_XYZ pMid = 0.5 * ( p1 + p2 );
+      const SMDS_MeshElement* face;
+      polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face );
+      polySeg.myVector       = polySeg.myMidProjPoint.XYZ() - pMid;
+
+      gp_XYZ faceNorm;
+      SMESH_MeshAlgos::FaceNormal( face, faceNorm );
+
+      if ( polySeg.myVector.Magnitude() < Precision::Confusion() ||
+           polySeg.myVector * faceNorm  < Precision::Confusion() )
+      {
+        polySeg.myVector = faceNorm;
+        polySeg.myMidProjPoint = pMid + faceNorm * ( p1 - p2 ).Modulus() * planarCoef;
+      }
+    }
+    else
+    {
+      polySeg.myVector = plnNorm ^ ( p1 - p2 );
+    }
+  }
+
+  // assure that inverse elements are constructed, avoid their concurrent building in threads
+  GetMeshDS()->nodesIterator()->next()->NbInverseElements();
+
+  // find paths
+
+  PolyPathCompute algo( theSegments, segPaths, myMesh );
+  OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 );
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+    if ( !algo.myErrors[ iSeg ].empty() )
+      throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() );
+
+  // create an 1D mesh
+
+  const SMDS_MeshNode *n, *nPrev = 0;
+  SMESHDS_Mesh* mesh = GetMeshDS();
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    const Path& path = segPaths[iSeg];
+    if ( path.myPoints.size() < 2 )
+      continue;
+
+    double tol = path.myLength / path.myPoints.size() / 1000.;
+    if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol )
+    {
+      nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() );
+      myLastCreatedNodes.push_back( nPrev );
+    }
+    for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+    {
+      n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
+      myLastCreatedNodes.push_back( n );
+
+      const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
+      myLastCreatedElems.push_back( elem );
+      if ( theGroup )
+        theGroup->Add( elem );
+
+      nPrev = n;
+    }
+
+    // return a vector
+
+    gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() );
+    if ( isVectorOK[ iSeg ])
+    {
+      // find the most distance point of a path
+      double maxDist = 0;
+      for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+      {
+        double dist = Abs( theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] ));
+        if ( dist > maxDist )
+        {
+          maxDist = dist;
+          theSegments[iSeg].myMidProjPoint = path.myPoints[iP];
+        }
+      }
+      if ( maxDist < Precision::Confusion() ) // planar case
+        theSegments[iSeg].myMidProjPoint =
+          pMid + theSegments[iSeg].myVector.XYZ().Normalized() * path.myLength * planarCoef;
+    }
+    theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint );
+  }
+
+  return;
+}