Salome HOME
#17636 [CEA 17369] Extrusion by normal: along average normal option issue
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index b11f6c32adc78541bcf1e5eeb10638a17f6b0974..7466070e46f335978bf01c4b6e44712c5ff055c7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -97,7 +97,6 @@
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx>
-#include <OSD_Parallel.hxx>
 
 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 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  :
@@ -147,8 +135,8 @@ SMESHDS_Mesh * SMESH_MeshEditor::GetMeshDS()
 
 void SMESH_MeshEditor::ClearLastCreated()
 {
-  myLastCreatedNodes.Clear();
-  myLastCreatedElems.Clear();
+  SMESHUtils::FreeVector( myLastCreatedElems );
+  SMESHUtils::FreeVector( myLastCreatedNodes );
 }
 
 //================================================================================
@@ -173,7 +161,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 );
         }
       }
@@ -380,7 +368,7 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
 
   default:;
   }
-  if ( e ) myLastCreatedElems.Append( e );
+  if ( e ) myLastCreatedElems.push_back( e );
   return e;
 }
 
@@ -414,8 +402,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;
@@ -495,7 +482,7 @@ void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& eleme
   }
   else
   {
-    elemIt = elemSetIterator( elements );
+    elemIt = SMESHUtils::elemSetIterator( elements );
   }
 
   while ( elemIt->more() )
@@ -508,8 +495,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() );
@@ -525,8 +512,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() )
@@ -620,25 +606,6 @@ static void shiftNodesQuadTria(vector< const SMDS_MeshNode* >& aNodes)
   aNodes[5] = nd2;
 }
 
-//=======================================================================
-//function : nbEdgeConnectivity
-//purpose  : return number of the edges connected with the theNode.
-//           if theEdges has connections with the other type of the
-//           elements, return -1
-//=======================================================================
-
-static int nbEdgeConnectivity(const SMDS_MeshNode* theNode)
-{
-  // SMDS_ElemIteratorPtr elemIt = theNode->GetInverseElementIterator();
-  // int nb=0;
-  // while(elemIt->more()) {
-  //   elemIt->next();
-  //   nb++;
-  // }
-  // return nb;
-  return theNode->NbInverseElements();
-}
-
 //=======================================================================
 //function : getNodesFromTwoTria
 //purpose  : 
@@ -693,19 +660,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 )   |\ |
     //    |/ |                                         | \|
@@ -819,9 +785,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
     {
@@ -894,17 +860,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)) {
 
@@ -1015,35 +980,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 );
 
@@ -1087,13 +1050,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 );
 
@@ -1110,8 +1073,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;
@@ -1126,8 +1088,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;
@@ -1185,7 +1146,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() );
   }
@@ -1316,7 +1277,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;
@@ -1405,17 +1366,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++ )
   {
@@ -1442,7 +1403,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     const SMDS_MeshElement* newElem1 = 0;
     const SMDS_MeshElement* newElem2 = 0;
 
-    if ( !elem->IsQuadratic() ) // split liner quadrangle
+    if ( !elem->IsQuadratic() ) // split linear quadrangle
     {
       // for MaxElementLength2D functor we return minimum diagonal for splitting,
       // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
@@ -1484,8 +1445,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 );
 
@@ -1508,15 +1469,15 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
 
 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);
@@ -1573,7 +1534,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 ] );
@@ -1600,7 +1561,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
@@ -1618,7 +1579,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
                                                nodes[(i+1)%4],
                                                nCentral );
       ReplaceElemInGroups( tria, quad, GetMeshDS() );
-      myLastCreatedElems.Append( tria );
+      myLastCreatedElems.push_back( tria );
     }
   }
 }
@@ -1631,8 +1592,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;
@@ -2299,7 +2259,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() )
     {
@@ -2313,7 +2273,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 );
       }
@@ -2324,18 +2284,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() );
 
@@ -2379,7 +2339,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 )
@@ -2388,7 +2348,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
@@ -2442,7 +2402,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 );
@@ -2479,7 +2439,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
 
@@ -2933,11 +2893,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() );
 
@@ -2967,8 +2926,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 )
       {
@@ -3010,7 +2969,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
@@ -3028,8 +2987,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 )
       {
@@ -3153,8 +3112,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;
@@ -3338,7 +3297,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 )
@@ -3369,7 +3328,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 )
@@ -3392,7 +3351,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 )
@@ -3423,7 +3382,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 )
@@ -3451,286 +3410,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
@@ -3936,8 +3615,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
                                double                      theTgtAspectRatio,
                                const bool                  the2D)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   if ( theTgtAspectRatio < 1.0 )
     theTgtAspectRatio = 1.0;
@@ -4130,7 +3808,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);
           }
@@ -4143,7 +3821,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
@@ -4385,7 +4063,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;
@@ -4399,9 +4077,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() );
           }
@@ -4429,8 +4107,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 );
 
@@ -4663,55 +4341,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;
 
@@ -4933,8 +4611,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
@@ -5024,19 +4702,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 );
         }
       }
     }
@@ -5064,14 +4742,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 );
           }
         }
       }
@@ -5092,15 +4770,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 );
           }
         }
       }
@@ -5134,9 +4812,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;
@@ -5193,8 +4871,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
@@ -5208,8 +4886,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
@@ -5227,12 +4905,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
@@ -5253,10 +4931,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
@@ -5278,11 +4956,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
@@ -5301,8 +4979,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
 
@@ -5339,8 +5017,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
@@ -5360,11 +5038,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 );
@@ -5384,7 +5067,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 )
   {
@@ -5436,8 +5118,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] );
               }
@@ -5446,8 +5128,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 {
@@ -5482,6 +5164,7 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet   theElemSets[2],
 SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&            theStep,
                                             const int                theNbSteps,
                                             const std::list<double>& theScales,
+                                            const std::list<double>& theAngles,
                                             const gp_XYZ*            theBasePoint,
                                             const int                theFlags,
                                             const double             theTolerance):
@@ -5496,32 +5179,52 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec&            theStep,
   for (int i=1; i<=theNbSteps; i++ )
     mySteps->Append( stepSize );
 
-  int nbScales = theScales.size();
-  if ( nbScales > 0 )
+  if ( !theScales.empty() )
   {
-    if ( IsLinearVariation() && nbScales < theNbSteps )
+    if ( IsScaleVariation() && (int)theScales.size() < theNbSteps )
+      linearScaleVariation( theNbSteps, const_cast< std::list<double>& >( theScales ));
+
+    // add medium scales
+    std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+    myScales.reserve( theNbSteps * 2 );
+    myScales.push_back( 0.5 * ( *s1 + 1. ));
+    myScales.push_back( *s1 );
+    for ( ; s2 != theScales.end(); s1 = s2++ )
     {
-      myScales.reserve( theNbSteps );
-      std::list<double>::const_iterator scale = theScales.begin();
-      double prevScale = 1.0;
-      for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
-      {
-        int      iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
-        int    stDelta = Max( 1, iStep - myScales.size());
-        double scDelta = ( *scale - prevScale ) / stDelta;
-        for ( int iStep = 0; iStep < stDelta; ++iStep )
-        {
-          myScales.push_back( prevScale + scDelta );
-          prevScale = myScales.back();
-        }
-        prevScale = *scale;
-      }
+      myScales.push_back( 0.5 * ( *s1 + *s2 ));
+      myScales.push_back( *s2 );
     }
-    else
+  }
+
+  if ( !theAngles.empty() )
+  {
+    std::list<double>& angles = const_cast< std::list<double>& >( theAngles );
+    if ( IsAngleVariation() && (int)theAngles.size() < theNbSteps )
+      linearAngleVariation( theNbSteps, angles );
+
+    // accumulate angles
+    double angle = 0;
+    int nbAngles = 0;
+    std::list<double>::iterator a1 = angles.begin(), a2;
+    for ( ; a1 != angles.end(); ++a1, ++nbAngles )
+    {
+      angle += *a1;
+      *a1 = angle;
+    }
+    while ( nbAngles++ < theNbSteps )
+      angles.push_back( angles.back() );
+
+    // add medium angles
+    a2 = angles.begin(), a1 = a2++;
+    myAngles.push_back( 0.5 * *a1 );
+    myAngles.push_back( *a1 );
+    for ( ; a2 != angles.end(); a1 = a2++ )
     {
-      myScales.assign( theScales.begin(), theScales.end() );
+      myAngles.push_back( 0.5 * ( *a1 + *a2 ));
+      myAngles.push_back( *a2 );
     }
   }
+
   if ( theBasePoint )
   {
     myBaseP = *theBasePoint;
@@ -5592,6 +5295,41 @@ SMESH_MeshEditor::ExtrusParam::ExtrusParam( const double theStepSize,
   }
 }
 
+//=======================================================================
+//function : ExtrusParam
+//purpose  : for extrusion along path
+//=======================================================================
+
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const std::vector< PathPoint >& thePoints,
+                                            const gp_Pnt*                   theBasePoint,
+                                            const std::list<double>&        theScales,
+                                            const bool                      theMakeGroups )
+  : myBaseP( Precision::Infinite(), 0, 0 ),
+    myFlags( EXTRUSION_FLAG_BOUNDARY | ( theMakeGroups ? EXTRUSION_FLAG_GROUPS : 0 )),
+    myPathPoints( thePoints )
+{
+  if ( theBasePoint )
+  {
+    myBaseP = theBasePoint->XYZ();
+  }
+
+  if ( !theScales.empty() )
+  {
+    // add medium scales
+    std::list<double>::const_iterator s2 = theScales.begin(), s1 = s2++;
+    myScales.reserve( thePoints.size() * 2 );
+    myScales.push_back( 0.5 * ( 1. + *s1 ));
+    myScales.push_back( *s1 );
+    for ( ; s2 != theScales.end(); s1 = s2++ )
+    {
+      myScales.push_back( 0.5 * ( *s1 + *s2 ));
+      myScales.push_back( *s2 );
+    }
+  }
+
+  myMakeNodesFun = & SMESH_MeshEditor::ExtrusParam::makeNodesAlongTrack;
+}
+
 //=======================================================================
 //function : ExtrusParam::SetElementsToUse
 //purpose  : stores elements to use for extrusion by normal, depending on
@@ -5621,7 +5359,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 );
         }
       }
     }
@@ -5687,7 +5425,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
@@ -5697,38 +5435,37 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
     newNodes.push_back( newNode );
   }
 
-  if ( !myScales.empty() )
+  if ( !myScales.empty() || !myAngles.empty() )
   {
-    if ( makeMediumNodes && myMediumScales.empty() )
-    {
-      myMediumScales.resize( myScales.size() );
-      double prevFactor = 1.;
-      for ( size_t i = 0; i < myScales.size(); ++i )
-      {
-        myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] );
-        prevFactor = myScales[i];
-      }
-    }
-    typedef std::vector<double>::iterator ScaleIt;
-    ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() };
+    gp_XYZ  center = myBaseP;
+    gp_Ax1  ratationAxis( center, myDir );
+    gp_Trsf rotation;
 
-    size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size();
-
-    gp_XYZ center = myBaseP;
     std::list<const SMDS_MeshNode*>::iterator nIt = newNodes.begin();
-    size_t iN  = 0;
-    for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN )
+    size_t i = !makeMediumNodes;
+    for ( beginStepIter( makeMediumNodes );
+          moreSteps();
+          ++nIt, i += 1 + !makeMediumNodes )
     {
       center += myDir.XYZ() * nextStep();
 
-      iSc += int( makeMediumNodes );
-      ScaleIt& scale = scales[ iSc % 2 ];
-      
-      gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
-      xyz = ( *scale * ( xyz - center )) + center;
-      mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
-
-      ++scale;
+      gp_XYZ xyz = SMESH_NodeXYZ( *nIt );
+      bool moved = false;
+      if ( i < myScales.size() )
+      {
+        xyz = ( myScales[i] * ( xyz - center )) + center;
+        moved = true;
+      }
+      if ( !myAngles.empty() )
+      {
+        rotation.SetRotation( ratationAxis, myAngles[i] );
+        rotation.Transforms( xyz );
+        moved = true;
+      }
+      if ( moved )
+        mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
+      else
+        break;
     }
   }
   return nbNodes;
@@ -5745,7 +5482,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
@@ -5753,13 +5490,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);
@@ -5767,10 +5505,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;
@@ -5802,7 +5542,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;
@@ -5822,7 +5562,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 );
       }
     }
@@ -5892,6 +5632,100 @@ makeNodesByNormal1D( SMESHDS_Mesh*                     mesh,
   return 0;
 }
 
+//=======================================================================
+//function : ExtrusParam::makeNodesAlongTrack
+//purpose  : create nodes for extrusion along path
+//=======================================================================
+
+int SMESH_MeshEditor::ExtrusParam::
+makeNodesAlongTrack( SMESHDS_Mesh*                     mesh,
+                     const SMDS_MeshNode*              srcNode,
+                     std::list<const SMDS_MeshNode*> & newNodes,
+                     const bool                        makeMediumNodes)
+{
+  const Standard_Real aTolAng=1.e-4;
+
+  gp_Pnt aV0x = myBaseP;
+  gp_Pnt aPN0 = SMESH_NodeXYZ( srcNode );
+
+  const PathPoint& aPP0 = myPathPoints[0];
+  gp_Pnt aP0x = aPP0.myPnt;
+  gp_Dir aDT0x= aPP0.myTgt;
+
+  std::vector< gp_Pnt > centers;
+  centers.reserve( NbSteps() * 2 );
+
+  gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
+
+  for ( size_t j = 1; j < myPathPoints.size(); ++j )
+  {
+    const PathPoint&  aPP  = myPathPoints[j];
+    const gp_Pnt&     aP1x = aPP.myPnt;
+    const gp_Dir&    aDT1x = aPP.myTgt;
+
+    // Translation
+    gp_Vec aV01x( aP0x, aP1x );
+    aTrsf.SetTranslation( aV01x );
+    gp_Pnt aV1x = aV0x.Transformed( aTrsf );
+    gp_Pnt aPN1 = aPN0.Transformed( aTrsf );
+
+    // rotation 1 [ T1,T0 ]
+    Standard_Real aAngleT1T0 = -aDT1x.Angle( aDT0x );
+    if ( fabs( aAngleT1T0 ) > aTolAng )
+    {
+      gp_Dir aDT1T0 = aDT1x ^ aDT0x;
+      aTrsfRotT1T0.SetRotation( gp_Ax1( aV1x, aDT1T0 ), aAngleT1T0 );
+
+      aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
+    }
+
+    // rotation 2
+    if ( aPP.myAngle != 0. )
+    {
+      aTrsfRot.SetRotation( gp_Ax1( aV1x, aDT1x ), aPP.myAngle );
+      aPN1 = aPN1.Transformed( aTrsfRot );
+    }
+
+    // make new node
+    if ( makeMediumNodes )
+    {
+      // create additional node
+      gp_XYZ midP = 0.5 * ( aPN1.XYZ() + aPN0.XYZ() );
+      const SMDS_MeshNode* newNode = mesh->AddNode( midP.X(), midP.Y(), midP.Z() );
+      newNodes.push_back( newNode );
+
+    }
+    const SMDS_MeshNode* newNode = mesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
+    newNodes.push_back( newNode );
+
+    centers.push_back( 0.5 * ( aV0x.XYZ() + aV1x.XYZ() ));
+    centers.push_back( aV1x );
+
+    aPN0 = aPN1;
+    aP0x = aP1x;
+    aV0x = aV1x;
+    aDT0x = aDT1x;
+  }
+
+  // scale
+  if ( !myScales.empty() )
+  {
+    gp_Trsf aTrsfScale;
+    std::list<const SMDS_MeshNode*>::iterator node = newNodes.begin();
+    for ( size_t i = !makeMediumNodes;
+          i < myScales.size() && node != newNodes.end();
+          i += ( 1 + !makeMediumNodes ), ++node )
+    {
+      aTrsfScale.SetScale( centers[ i ], myScales[ i ] );
+      gp_Pnt aN = SMESH_NodeXYZ( *node );
+      gp_Pnt aP = aN.Transformed( aTrsfScale );
+      mesh->MoveNode( *node, aP.X(), aP.Y(), aP.Z() );
+    }
+  }
+
+  return myPathPoints.size() + makeMediumNodes * ( myPathPoints.size() - 2 );
+}
+
 //=======================================================================
 //function : ExtrusionSweep
 //purpose  :
@@ -5905,10 +5739,31 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElems[2],
                                   const int            theFlags,
                                   const double         theTolerance)
 {
-  ExtrusParam aParams( theStep, theNbSteps, std::list<double>(), 0, theFlags, theTolerance );
+  std::list<double> dummy;
+  ExtrusParam aParams( theStep, theNbSteps, dummy, dummy, 0,
+                       theFlags, theTolerance );
   return ExtrusionSweep( theElems, aParams, newElemsMap );
 }
 
+namespace
+{
+
+//=======================================================================
+//function : getOriFactor
+//purpose  : Return -1 or 1 depending on if order of given nodes corresponds to
+//           edge curve orientation
+//=======================================================================
+
+  double getOriFactor( const TopoDS_Edge&   edge,
+                       const SMDS_MeshNode* n1,
+                       const SMDS_MeshNode* n2,
+                       SMESH_MesherHelper&  helper)
+  {
+    double u1 = helper.GetNodeU( edge, n1, n2 );
+    double u2 = helper.GetNodeU( edge, n2, n1 );
+    return u1 < u2 ? 1. : -1.;
+  }
+}
 
 //=======================================================================
 //function : ExtrusionSweep
@@ -5920,13 +5775,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] );
 
@@ -5953,11 +5812,11 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
       newNodesItVec.reserve( nbNodes );
 
       // loop on elem nodes
-      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      SMDS_NodeIteratorPtr itN = elem->nodeIterator();
       while ( itN->more() )
       {
         // check if a node has been already sweeped
-        const SMDS_MeshNode* node = cast2Node( itN->next() );
+        const SMDS_MeshNode* node = itN->next();
         TNodeOfNodeListMap::iterator nIt =
           mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
         list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
@@ -5985,12 +5844,17 @@ 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
           {
+            if ( theParams.ToMakeBoundary() )
+            {
+              GetMeshDS()->Modified();
+              throw SALOME_Exception( SMESH_Comment("Can't extrude node #") << node->GetID() );
+            }
             break; // newNodesItVec will be shorter than nbNodes
           }
         }
@@ -6018,732 +5882,183 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet     theElemSets[2],
 //=======================================================================
 SMESH_MeshEditor::Extrusion_Error
 SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_subMesh*       theTrack,
+                                       SMESH_Mesh*          theTrackMesh,
+                                       SMDS_ElemIteratorPtr theTrackIterator,
                                        const SMDS_MeshNode* theN1,
-                                       const bool           theHasAngles,
-                                       list<double>&        theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
+                                       std::list<double>&   theAngles,
+                                       const bool           theAngleVariation,
+                                       std::list<double>&   theScales,
+                                       const bool           theScaleVariation,
+                                       const gp_Pnt*        theRefPoint,
                                        const bool           theMakeGroups)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
-
-  int aNbE;
-  std::list<double> aPrms;
-  TIDSortedElemSet::iterator itElem;
-
-  gp_XYZ aGC;
-  TopoDS_Edge aTrackEdge;
-  TopoDS_Vertex aV1, aV2;
-
-  SMDS_ElemIteratorPtr aItE;
-  SMDS_NodeIteratorPtr aItN;
-  SMDSAbs_ElementType aTypeE;
-
-  TNodeOfNodeListMap mapNewNodes;
+  ClearLastCreated();
 
   // 1. Check data
-  aNbE = theElements[0].size() + theElements[1].size();
-  // nothing to do
-  if ( !aNbE )
+  if ( theElements[0].empty() && theElements[1].empty() )
     return EXTR_NO_ELEMENTS;
 
-  // 1.1 Track Pattern
-  ASSERT( theTrack );
-
-  SMESHDS_SubMesh* pSubMeshDS = theTrack->GetSubMeshDS();
-  if ( !pSubMeshDS )
-    return ExtrusionAlongTrack( theElements, theTrack->GetFather(), theN1,
-                                theHasAngles, theAngles, theLinearVariation,
-                                theHasRefPoint, theRefPoint, theMakeGroups );
-
-  aItE = pSubMeshDS->GetElements();
-  while ( aItE->more() ) {
-    const SMDS_MeshElement* pE = aItE->next();
-    aTypeE = pE->GetType();
-    // Pattern must contain links only
-    if ( aTypeE != SMDSAbs_Edge )
-      return EXTR_PATH_NOT_EDGE;
-  }
-
-  list<SMESH_MeshEditor_PathPoint> fullList;
-
-  const TopoDS_Shape& aS = theTrack->GetSubShape();
-  // Sub-shape for the Pattern must be an Edge or Wire
-  if( aS.ShapeType() == TopAbs_EDGE ) {
-    aTrackEdge = TopoDS::Edge( aS );
-    // the Edge must not be degenerated
-    if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
-      return EXTR_BAD_PATH_SHAPE;
-    TopExp::Vertices( aTrackEdge, aV1, aV2 );
-    aItN = theTrack->GetFather()->GetSubMesh( aV1 )->GetSubMeshDS()->GetNodes();
-    const SMDS_MeshNode* aN1 = aItN->next();
-    aItN = theTrack->GetFather()->GetSubMesh( aV2 )->GetSubMeshDS()->GetNodes();
-    const SMDS_MeshNode* aN2 = aItN->next();
-    // starting node must be aN1 or aN2
-    if ( !( aN1 == theN1 || aN2 == theN1 ) )
-      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() );
-      double aT = pEPos->GetUParameter();
-      aPrms.push_back( aT );
-    }
-    //Extrusion_Error err =
-    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
-  } else if( aS.ShapeType() == TopAbs_WIRE ) {
-    list< SMESH_subMesh* > LSM;
-    TopTools_SequenceOfShape Edges;
-    SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
-    while(itSM->more()) {
-      SMESH_subMesh* SM = itSM->next();
-      LSM.push_back(SM);
-      const TopoDS_Shape& aS = SM->GetSubShape();
-      Edges.Append(aS);
-    }
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    int startNid = theN1->GetID();
-    TColStd_MapOfInteger UsedNums;
-
-    int NbEdges = Edges.Length();
-    int i = 1;
-    for(; i<=NbEdges; i++) {
-      int k = 0;
-      list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
-      for(; itLSM!=LSM.end(); itLSM++) {
-        k++;
-        if(UsedNums.Contains(k)) continue;
-        aTrackEdge = TopoDS::Edge( Edges.Value(k) );
-        SMESH_subMesh* locTrack = *itLSM;
-        SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
-        TopExp::Vertices( aTrackEdge, aV1, aV2 );
-        aItN = locTrack->GetFather()->GetSubMesh(aV1)->GetSubMeshDS()->GetNodes();
-        const SMDS_MeshNode* aN1 = aItN->next();
-        aItN = locTrack->GetFather()->GetSubMesh(aV2)->GetSubMeshDS()->GetNodes();
-        const SMDS_MeshNode* aN2 = aItN->next();
-        // starting node must be aN1 or aN2
-        if ( !( aN1->GetID() == startNid || aN2->GetID() == startNid ) ) continue;
-        // 2. Collect parameters on the track edge
-        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() );
-          double aT = pEPos->GetUParameter();
-          aPrms.push_back( aT );
-        }
-        list<SMESH_MeshEditor_PathPoint> LPP;
-        //Extrusion_Error err =
-        makeEdgePathPoints(aPrms, aTrackEdge,(aN1->GetID()==startNid), LPP);
-        LLPPs.push_back(LPP);
-        UsedNums.Add(k);
-        // update startN for search following edge
-        if( aN1->GetID() == startNid ) startNid = aN2->GetID();
-        else startNid = aN1->GetID();
-        break;
-      }
-    }
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
-    list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
-    for(; itPP!=firstList.end(); itPP++) {
-      fullList.push_back( *itPP );
-    }
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
-      itPP = currList.begin();
-      SMESH_MeshEditor_PathPoint PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( gp_Vec( (D1.X()+D2.X())/2, (D1.Y()+D2.Y())/2,
-                           (D1.Z()+D2.Z())/2 ) );
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      itPP++;
-      for(; itPP!=firstList.end(); itPP++) {
-        fullList.push_back( *itPP );
-      }
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    // if wire not closed
-    fullList.push_back(PP1);
-    // else ???
-  }
-  else {
-    return EXTR_BAD_PATH_SHAPE;
-  }
-
-  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
-                          theHasRefPoint, theRefPoint, theMakeGroups);
-}
-
-
-//=======================================================================
-//function : ExtrusionAlongTrack
-//purpose  :
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
-                                       SMESH_Mesh*          theTrack,
-                                       const SMDS_MeshNode* theN1,
-                                       const bool           theHasAngles,
-                                       list<double>&        theAngles,
-                                       const bool           theLinearVariation,
-                                       const bool           theHasRefPoint,
-                                       const gp_Pnt&        theRefPoint,
-                                       const bool           theMakeGroups)
-{
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
-
-  int aNbE;
-  std::list<double> aPrms;
-  TIDSortedElemSet::iterator itElem;
-
-  gp_XYZ aGC;
-  TopoDS_Edge aTrackEdge;
-  TopoDS_Vertex aV1, aV2;
+  ASSERT( theTrackMesh );
+  if ( ! theTrackIterator || !theTrackIterator->more() )
+    return EXTR_NO_ELEMENTS;
 
-  SMDS_ElemIteratorPtr aItE;
-  SMDS_NodeIteratorPtr aItN;
-  SMDSAbs_ElementType aTypeE;
+  // 2. Get ordered nodes
+  SMESH_MeshAlgos::TElemGroupVector branchEdges;
+  SMESH_MeshAlgos::TNodeGroupVector branchNods;
+  SMESH_MeshAlgos::Get1DBranches( theTrackIterator, branchEdges, branchNods, theN1 );
+  if ( branchEdges.empty() )
+    return EXTR_PATH_NOT_EDGE;
 
-  TNodeOfNodeListMap mapNewNodes;
-
-  // 1. Check data
-  aNbE = theElements[0].size() + theElements[1].size();
-  // nothing to do
-  if ( !aNbE )
-    return EXTR_NO_ELEMENTS;
+  if ( branchEdges.size() > 1 )
+    return EXTR_BAD_PATH_SHAPE;
 
-  // 1.1 Track Pattern
-  ASSERT( theTrack );
-
-  SMESHDS_Mesh* pMeshDS = theTrack->GetMeshDS();
-
-  aItE = pMeshDS->elementsIterator();
-  while ( aItE->more() ) {
-    const SMDS_MeshElement* pE = aItE->next();
-    aTypeE = pE->GetType();
-    // Pattern must contain links only
-    if ( aTypeE != SMDSAbs_Edge )
-      return EXTR_PATH_NOT_EDGE;
-  }
-
-  list<SMESH_MeshEditor_PathPoint> fullList;
-
-  const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
-
-  if ( !theTrack->HasShapeToMesh() ) {
-    //Mesh without shape
-    const SMDS_MeshNode* currentNode = NULL;
-    const SMDS_MeshNode* prevNode = theN1;
-    std::vector<const SMDS_MeshNode*> aNodesList;
-    aNodesList.push_back(theN1);
-    int nbEdges = 0, conn=0;
-    const SMDS_MeshElement* prevElem = NULL;
-    const SMDS_MeshElement* currentElem = NULL;
-    int totalNbEdges = theTrack->NbEdges();
-    SMDS_ElemIteratorPtr nIt;
-
-    //check start node
-    if( !theTrack->GetMeshDS()->Contains(theN1) ) {
-      return EXTR_BAD_STARTING_NODE;
-    }
-
-    conn = nbEdgeConnectivity(theN1);
-    if( conn != 1 )
-      return EXTR_PATH_NOT_EDGE;
-
-    aItE = theN1->GetInverseElementIterator();
-    prevElem = aItE->next();
-    currentElem = prevElem;
-    //Get all nodes
-    if(totalNbEdges == 1 ) {
-      nIt = currentElem->nodesIterator();
-      currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-      if(currentNode == prevNode)
-        currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-      aNodesList.push_back(currentNode);
-    } else {
-      nIt = currentElem->nodesIterator();
-      while( nIt->more() ) {
-        currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-        if(currentNode == prevNode)
-          currentNode = static_cast<const SMDS_MeshNode*>(nIt->next());
-        aNodesList.push_back(currentNode);
-
-        //case of the closed mesh
-        if(currentNode == theN1) {
-          nbEdges++;
-          break;
-        }
+  std::vector< const SMDS_MeshNode* >&    pathNodes = branchNods[0];
+  std::vector< const SMDS_MeshElement* >& pathEdges = branchEdges[0];
+  if ( pathNodes[0] != theN1 && pathNodes[1] != theN1 )
+    return EXTR_BAD_STARTING_NODE;
 
-        conn = nbEdgeConnectivity(currentNode);
-        if(conn > 2) {
-          return EXTR_PATH_NOT_EDGE;
-        }else if( conn == 1 && nbEdges > 0 ) {
-          //End of the path
-          nbEdges++;
-          break;
-        }else {
-          prevNode = currentNode;
-          aItE = currentNode->GetInverseElementIterator();
-          currentElem = aItE->next();
-          if( currentElem  == prevElem)
-            currentElem = aItE->next();
-          nIt = currentElem->nodesIterator();
-          prevElem = currentElem;
-          nbEdges++;
-        }
-      }
-    }
-
-    if(nbEdges != totalNbEdges)
-      return EXTR_PATH_NOT_EDGE;
-
-    TopTools_SequenceOfShape Edges;
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    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] );
-      TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
-      list<SMESH_MeshEditor_PathPoint> LPP;
-      aPrms.clear();
-      makeEdgePathPoints(aPrms, e, (aNodesList[i-1]->GetID()==startNid), LPP);
-      LLPPs.push_back(LPP);
-      if ( aNodesList[i-1]->GetID() == startNid ) startNid = aNodesList[i  ]->GetID();
-      else                                        startNid = aNodesList[i-1]->GetID();
-    }
-
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint> firstList = *itLLPP;
-    list<SMESH_MeshEditor_PathPoint>::iterator itPP = firstList.begin();
-    for(; itPP!=firstList.end(); itPP++) {
-      fullList.push_back( *itPP );
-    }
-
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    SMESH_MeshEditor_PathPoint PP2;
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
-      itPP = currList.begin();
-      PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( 0.5 * ( D1.XYZ() + D2.XYZ() ));
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      itPP++;
-      for(; itPP!=currList.end(); itPP++) {
-        fullList.push_back( *itPP );
-      }
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    fullList.push_back(PP1);
-
-  } // Sub-shape for the Pattern must be an Edge or Wire
-  else if ( aS.ShapeType() == TopAbs_EDGE )
-  {
-    aTrackEdge = TopoDS::Edge( aS );
-    // the Edge must not be degenerated
-    if ( SMESH_Algo::isDegenerated( aTrackEdge ) )
-      return EXTR_BAD_PATH_SHAPE;
-    TopExp::Vertices( aTrackEdge, aV1, aV2 );
-    const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
-    const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
-    // starting node must be aN1 or aN2
-    if ( !( aN1 == theN1 || aN2 == theN1 ) )
-      return EXTR_BAD_STARTING_NODE;
-    aItN = pMeshDS->nodesIterator();
-    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() );
-      double aT = pEPos->GetUParameter();
-      aPrms.push_back( aT );
-    }
-    //Extrusion_Error err =
-    makeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
-  }
-  else if( aS.ShapeType() == TopAbs_WIRE ) {
-    list< SMESH_subMesh* > LSM;
-    TopTools_SequenceOfShape Edges;
-    TopExp_Explorer eExp(aS, TopAbs_EDGE);
-    for(; eExp.More(); eExp.Next()) {
-      TopoDS_Edge E = TopoDS::Edge( eExp.Current() );
-      if( SMESH_Algo::isDegenerated(E) ) continue;
-      SMESH_subMesh* SM = theTrack->GetSubMesh(E);
-      if(SM) {
-        LSM.push_back(SM);
-        Edges.Append(E);
-      }
-    }
-    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
-    TopoDS_Vertex aVprev;
-    TColStd_MapOfInteger UsedNums;
-    int NbEdges = Edges.Length();
-    int i = 1;
-    for(; i<=NbEdges; i++) {
-      int k = 0;
-      list< SMESH_subMesh* >::iterator itLSM = LSM.begin();
-      for(; itLSM!=LSM.end(); itLSM++) {
-        k++;
-        if(UsedNums.Contains(k)) continue;
-        aTrackEdge = TopoDS::Edge( Edges.Value(k) );
-        SMESH_subMesh* locTrack = *itLSM;
-        SMESHDS_SubMesh* locMeshDS = locTrack->GetSubMeshDS();
-        TopExp::Vertices( aTrackEdge, aV1, aV2 );
-        bool aN1isOK = false, aN2isOK = false;
-        if ( aVprev.IsNull() ) {
-          // if previous vertex is not yet defined, it means that we in the beginning of wire
-          // and we have to find initial vertex corresponding to starting node theN1
-          const SMDS_MeshNode* aN1 = SMESH_Algo::VertexNode( aV1, pMeshDS );
-          const SMDS_MeshNode* aN2 = SMESH_Algo::VertexNode( aV2, pMeshDS );
-          // starting node must be aN1 or aN2
-          aN1isOK = ( aN1 && aN1 == theN1 );
-          aN2isOK = ( aN2 && aN2 == theN1 );
-        }
-        else {
-          // we have specified ending vertex of the previous edge on the previous iteration
-          // and we have just to check that it corresponds to any vertex in current segment
-          aN1isOK = aVprev.IsSame( aV1 );
-          aN2isOK = aVprev.IsSame( aV2 );
-        }
-        if ( !aN1isOK && !aN2isOK ) continue;
-        // 2. Collect parameters on the track edge
-        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() );
-          double aT = pEPos->GetUParameter();
-          aPrms.push_back( aT );
-        }
-        list<SMESH_MeshEditor_PathPoint> LPP;
-        //Extrusion_Error err =
-        makeEdgePathPoints(aPrms, aTrackEdge, aN1isOK, LPP);
-        LLPPs.push_back(LPP);
-        UsedNums.Add(k);
-        // update startN for search following edge
-        if ( aN1isOK ) aVprev = aV2;
-        else           aVprev = aV1;
-        break;
+  if ( theTrackMesh->NbEdges( ORDER_QUADRATIC ) > 0 )
+  {
+    // add medium nodes to pathNodes
+    std::vector< const SMDS_MeshNode* >    pathNodes2;
+    std::vector< const SMDS_MeshElement* > pathEdges2;
+    pathNodes2.reserve( pathNodes.size() * 2 );
+    pathEdges2.reserve( pathEdges.size() * 2 );
+    for ( size_t i = 0; i < pathEdges.size(); ++i )
+    {
+      pathNodes2.push_back( pathNodes[i] );
+      pathEdges2.push_back( pathEdges[i] );
+      if ( pathEdges[i]->IsQuadratic() )
+      {
+        pathNodes2.push_back( pathEdges[i]->GetNode(2) );
+        pathEdges2.push_back( pathEdges[i] );
       }
     }
-    list< list<SMESH_MeshEditor_PathPoint> >::iterator itLLPP = LLPPs.begin();
-    list<SMESH_MeshEditor_PathPoint>& firstList = *itLLPP;
-    fullList.splice( fullList.end(), firstList );
-
-    SMESH_MeshEditor_PathPoint PP1 = fullList.back();
-    fullList.pop_back();
-    itLLPP++;
-    for(; itLLPP!=LLPPs.end(); itLLPP++) {
-      list<SMESH_MeshEditor_PathPoint>& currList = *itLLPP;
-      SMESH_MeshEditor_PathPoint PP2 = currList.front();
-      gp_Dir D1 = PP1.Tangent();
-      gp_Dir D2 = PP2.Tangent();
-      gp_Dir Dnew( D1.XYZ() + D2.XYZ() );
-      PP1.SetTangent(Dnew);
-      fullList.push_back(PP1);
-      fullList.splice( fullList.end(), currList, ++currList.begin(), currList.end() );
-      PP1 = fullList.back();
-      fullList.pop_back();
-    }
-    // if wire not closed
-    fullList.push_back(PP1);
-    // else ???
-  }
-  else {
-    return EXTR_BAD_PATH_SHAPE;
+    pathNodes2.push_back( pathNodes.back() );
+    pathEdges.swap( pathEdges2 );
+    pathNodes.swap( pathNodes2 );
   }
 
-  return makeExtrElements(theElements, fullList, theHasAngles, theAngles, theLinearVariation,
-                          theHasRefPoint, theRefPoint, theMakeGroups);
-}
+  // 3. Get path data at pathNodes
 
+  std::vector< ExtrusParam::PathPoint > points( pathNodes.size() );
 
-//=======================================================================
-//function : makeEdgePathPoints
-//purpose  : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeEdgePathPoints(std::list<double>&                aPrms,
-                                     const TopoDS_Edge&                aTrackEdge,
-                                     bool                              FirstIsStart,
-                                     list<SMESH_MeshEditor_PathPoint>& LPP)
-{
-  Standard_Real aTx1, aTx2, aL2, aTolVec, aTolVec2;
-  aTolVec=1.e-7;
-  aTolVec2=aTolVec*aTolVec;
-  double aT1, aT2;
-  TopoDS_Vertex aV1, aV2;
-  TopExp::Vertices( aTrackEdge, aV1, aV2 );
-  aT1=BRep_Tool::Parameter( aV1, aTrackEdge );
-  aT2=BRep_Tool::Parameter( aV2, aTrackEdge );
-  // 2. Collect parameters on the track edge
-  aPrms.push_front( aT1 );
-  aPrms.push_back( aT2 );
-  // sort parameters
-  aPrms.sort();
-  if( FirstIsStart ) {
-    if ( aT1 > aT2 ) {
-      aPrms.reverse();
-    }
-  }
-  else {
-    if ( aT2 > aT1 ) {
-      aPrms.reverse();
-    }
-  }
-  // 3. Path Points
-  SMESH_MeshEditor_PathPoint aPP;
-  Handle(Geom_Curve) aC3D = BRep_Tool::Curve( aTrackEdge, aTx1, aTx2 );
-  std::list<double>::iterator aItD = aPrms.begin();
-  for(; aItD != aPrms.end(); ++aItD) {
-    double aT = *aItD;
-    gp_Pnt aP3D;
-    gp_Vec aVec;
-    aC3D->D1( aT, aP3D, aVec );
-    aL2 = aVec.SquareMagnitude();
-    if ( aL2 < aTolVec2 )
-      return EXTR_CANT_GET_TANGENT;
-    gp_Dir aTgt( FirstIsStart ? aVec : -aVec );
-    aPP.SetPnt( aP3D );
-    aPP.SetTangent( aTgt );
-    aPP.SetParameter( aT );
-    LPP.push_back(aPP);
-  }
-  return EXTR_OK;
-}
+  if ( theAngleVariation )
+    linearAngleVariation( points.size()-1, theAngles );
+  if ( theScaleVariation )
+    linearScaleVariation( points.size()-1, theScales );
 
+  theAngles.push_front( 0 ); // for the 1st point that is not transformed
+  std::list<double>::iterator angle = theAngles.begin();
 
-//=======================================================================
-//function : makeExtrElements
-//purpose  : auxiliary for ExtrusionAlongTrack
-//=======================================================================
-SMESH_MeshEditor::Extrusion_Error
-SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets[2],
-                                   list<SMESH_MeshEditor_PathPoint>& fullList,
-                                   const bool                        theHasAngles,
-                                   list<double>&                     theAngles,
-                                   const bool                        theLinearVariation,
-                                   const bool                        theHasRefPoint,
-                                   const gp_Pnt&                     theRefPoint,
-                                   const bool                        theMakeGroups)
-{
-  const int aNbTP = fullList.size();
+  SMESHDS_Mesh* pathMeshDS = theTrackMesh->GetMeshDS();
 
-  // Angles
-  if( theHasAngles && !theAngles.empty() && theLinearVariation )
-    linearAngleVariation(aNbTP-1, theAngles);
+  std::map< int, double > edgeID2OriFactor; // orientation of EDGEs
+  std::map< int, double >::iterator id2factor;
+  SMESH_MesherHelper pathHelper( *theTrackMesh );
+  gp_Pnt p; gp_Vec tangent;
+  const double tol2 = gp::Resolution() * gp::Resolution();
 
-  // fill vector of path points with angles
-  vector<SMESH_MeshEditor_PathPoint> aPPs;
-  list<SMESH_MeshEditor_PathPoint>::iterator itPP = fullList.begin();
-  list<double>::iterator                 itAngles = theAngles.begin();
-  aPPs.push_back( *itPP++ );
-  for( ; itPP != fullList.end(); itPP++) {
-    aPPs.push_back( *itPP );
-    if ( theHasAngles && itAngles != theAngles.end() )
-      aPPs.back().SetAngle( *itAngles++ );
-  }
+  for ( size_t i = 0; i < pathNodes.size(); ++i )
+  {
+    ExtrusParam::PathPoint & point = points[ i ];
 
-  TNodeOfNodeListMap   mapNewNodes;
-  TElemOfVecOfNnlmiMap mapElemNewNodes;
-  TTElemOfElemListMap  newElemsMap;
-  TIDSortedElemSet::iterator itElem;
-  // source elements for each generated one
-  SMESH_SequenceOfElemPtr srcElems, srcNodes;
+    point.myPnt = SMESH_NodeXYZ( pathNodes[ i ]);
 
-  // 3. Center of rotation aV0
-  gp_Pnt aV0 = theRefPoint;
-  if ( !theHasRefPoint )
-  {
-    gp_XYZ aGC( 0.,0.,0. );
-    TIDSortedElemSet newNodes;
+    if ( angle != theAngles.end() )
+      point.myAngle = *angle++;
 
-    for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
+    tangent.SetCoord( 0,0,0 );
+    const int          shapeID = pathNodes[ i ]->GetShapeID();
+    const TopoDS_Shape&  shape = pathMeshDS->IndexToShape( shapeID );
+    TopAbs_ShapeEnum shapeType = shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
+    switch ( shapeType )
     {
-      TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
-      itElem = theElements.begin();
-      for ( ; itElem != theElements.end(); itElem++ )
+    case TopAbs_EDGE:
+    {
+      TopoDS_Edge edge = TopoDS::Edge( shape );
+      id2factor = edgeID2OriFactor.insert( std::make_pair( shapeID, 0 )).first;
+      if ( id2factor->second == 0 )
       {
-        const SMDS_MeshElement* elem = *itElem;
-        SMDS_ElemIteratorPtr     itN = elem->nodesIterator();
-        while ( itN->more() ) {
-          const SMDS_MeshElement* node = itN->next();
-          if ( newNodes.insert( node ).second )
-            aGC += SMESH_TNodeXYZ( node );
-        }
+        if ( i ) id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+        else     id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
       }
+      double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+      Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+      curve->D1( u, p, tangent );
+      tangent *= id2factor->second;
+      break;
     }
-    aGC /= newNodes.size();
-    aV0.SetXYZ( aGC );
-  } // if (!theHasRefPoint) {
-
-  // 4. Processing the elements
-  SMESHDS_Mesh* aMesh = GetMeshDS();
-  list<const SMDS_MeshNode*> emptyList;
-
-  setElemsFirst( theElemSets );
-  for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
-  {
-    TIDSortedElemSet& theElements = theElemSets[ is2ndSet ];
-    for ( itElem = theElements.begin(); itElem != theElements.end(); itElem++ )
+    case TopAbs_VERTEX:
     {
-      const SMDS_MeshElement* elem = *itElem;
-
-      vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
-      newNodesItVec.reserve( elem->NbNodes() );
-
-      // loop on elem nodes
-      int nodeIndex = -1;
-      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-      while ( itN->more() )
+      int nbEdges = 0;
+      PShapeIteratorPtr shapeIt = pathHelper.GetAncestors( shape, *theTrackMesh, TopAbs_EDGE );
+      while ( const TopoDS_Shape* edgePtr = shapeIt->next() )
       {
-        ++nodeIndex;
-        // check if a node has been already processed
-        const SMDS_MeshNode* node = cast2Node( itN->next() );
-        TNodeOfNodeListMap::iterator nIt = mapNewNodes.insert( make_pair( node, emptyList )).first;
-        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
-        if ( listNewNodes.empty() )
+        int edgeID = pathMeshDS->ShapeToIndex( *edgePtr );
+        for ( int di = -1; di <= 0; ++di )
         {
-          // make new nodes
-          Standard_Real aAngle1x, aAngleT1T0, aTolAng;
-          gp_Pnt aP0x, aP1x, aPN0, aPN1, aV0x, aV1x;
-          gp_Ax1 anAx1, anAxT1T0;
-          gp_Dir aDT1x, aDT0x, aDT1T0;
-
-          aTolAng=1.e-4;
-
-          aV0x = aV0;
-          aPN0 = SMESH_TNodeXYZ( node );
-
-          const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
-          aP0x = aPP0.Pnt();
-          aDT0x= aPP0.Tangent();
-
-          for ( int j = 1; j < aNbTP; ++j ) {
-            const SMESH_MeshEditor_PathPoint& aPP1 = aPPs[j];
-            aP1x     = aPP1.Pnt();
-            aDT1x    = aPP1.Tangent();
-            aAngle1x = aPP1.Angle();
-
-            gp_Trsf aTrsf, aTrsfRot, aTrsfRotT1T0;
-            // Translation
-            gp_Vec aV01x( aP0x, aP1x );
-            aTrsf.SetTranslation( aV01x );
-
-            // traslated point
-            aV1x = aV0x.Transformed( aTrsf );
-            aPN1 = aPN0.Transformed( aTrsf );
-
-            // rotation 1 [ T1,T0 ]
-            aAngleT1T0=-aDT1x.Angle( aDT0x );
-            if (fabs(aAngleT1T0) > aTolAng)
+          size_t j = i + di;
+          if ( j < pathEdges.size() && edgeID == pathEdges[ j ]->GetShapeID() )
+          {
+            TopoDS_Edge edge = TopoDS::Edge( *edgePtr );
+            id2factor = edgeID2OriFactor.insert( std::make_pair( edgeID, 0 )).first;
+            if ( id2factor->second == 0 )
             {
-              aDT1T0=aDT1x^aDT0x;
-              anAxT1T0.SetLocation( aV1x );
-              anAxT1T0.SetDirection( aDT1T0 );
-              aTrsfRotT1T0.SetRotation( anAxT1T0, aAngleT1T0 );
-
-              aPN1 = aPN1.Transformed( aTrsfRotT1T0 );
-            }
-
-            // rotation 2
-            if ( theHasAngles ) {
-              anAx1.SetLocation( aV1x );
-              anAx1.SetDirection( aDT1x );
-              aTrsfRot.SetRotation( anAx1, aAngle1x );
-
-              aPN1 = aPN1.Transformed( aTrsfRot );
+              if ( j < i )
+                id2factor->second = getOriFactor( edge, pathNodes[i-1], pathNodes[i], pathHelper );
+              else
+                id2factor->second = getOriFactor( edge, pathNodes[i], pathNodes[i+1], pathHelper );
             }
-
-            // make new node
-            if ( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+            double u = pathHelper.GetNodeU( edge, pathNodes[i] ), u0, u1;
+            Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, u0, u1 );
+            gp_Vec du;
+            curve->D1( u, p, du );
+            double size2 = du.SquareMagnitude();
+            if ( du.SquareMagnitude() > tol2 )
             {
-              // 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 );
-              listNewNodes.push_back( newNode );
+              tangent += du.Divided( Sqrt( size2 )) * id2factor->second;
+              nbEdges++;
             }
-            const SMDS_MeshNode* newNode = aMesh->AddNode( aPN1.X(), aPN1.Y(), aPN1.Z() );
-            myLastCreatedNodes.Append(newNode);
-            srcNodes.Append( node );
-            listNewNodes.push_back( newNode );
-
-            aPN0 = aPN1;
-            aP0x = aP1x;
-            aV0x = aV1x;
-            aDT0x = aDT1x;
+            break;
           }
         }
-        else if( elem->IsQuadratic() && !elem->IsMediumNode(node) )
+      }
+      if ( nbEdges > 0 )
+        break;
+    }
+    default:
+    {
+      for ( int di = -1; di <= 1; di += 2 )
+      {
+        size_t j = i + di;
+        if ( j < pathNodes.size() )
         {
-          // if current elem is quadratic and current node is not medium
-          // we have to check - may be it is needed to insert additional nodes
-          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
-          if ((int) listNewNodes.size() == aNbTP-1 )
-          {
-            vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
-            gp_XYZ P(node->X(), node->Y(), node->Z());
-            list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
-            int i;
-            for(i=0; i<aNbTP-1; i++) {
-              const SMDS_MeshNode* N = *it;
-              double x = ( N->X() + P.X() )/2.;
-              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);
-              aNodes[2*i] = newN;
-              aNodes[2*i+1] = N;
-              P = gp_XYZ(N->X(),N->Y(),N->Z());
-            }
-            listNewNodes.clear();
-            for(i=0; i<2*(aNbTP-1); i++) {
-              listNewNodes.push_back(aNodes[i]);
-            }
-          }
+          gp_Vec dir( point.myPnt, SMESH_NodeXYZ( pathNodes[ j ]));
+          double size2 = dir.SquareMagnitude();
+          if ( size2 > tol2 )
+            tangent += dir.Divided( Sqrt( size2 )) * di;
         }
-
-        newNodesItVec.push_back( nIt );
       }
-
-      // make new elements
-      sweepElement( elem, newNodesItVec, newElemsMap[elem], aNbTP-1, srcElems );
     }
-  }
+    } // switch ( shapeType )
+
+    if ( tangent.SquareMagnitude() < tol2 )
+      return EXTR_CANT_GET_TANGENT;
 
-  makeWalls( mapNewNodes, newElemsMap, mapElemNewNodes, theElemSets[0], aNbTP-1, srcElems );
+    point.myTgt = tangent;
 
-  if ( theMakeGroups )
-    generateGroups( srcNodes, srcElems, "extruded");
+  } // loop on pathNodes
+
+
+  ExtrusParam nodeMaker( points, theRefPoint, theScales, theMakeGroups );
+  TTElemOfElemListMap newElemsMap;
+
+  ExtrusionSweep( theElements, nodeMaker, newElemsMap );
 
   return EXTR_OK;
 }
 
-
 //=======================================================================
 //function : linearAngleVariation
 //purpose  : spread values over nbSteps
@@ -6788,6 +6103,33 @@ void SMESH_MeshEditor::linearAngleVariation(const int     nbSteps,
   }
 }
 
+//=======================================================================
+//function : linearScaleVariation
+//purpose  : spread values over nbSteps 
+//=======================================================================
+
+void SMESH_MeshEditor::linearScaleVariation(const int          theNbSteps,
+                                            std::list<double>& theScales)
+{
+  int nbScales = theScales.size();
+  std::vector<double> myScales;
+  myScales.reserve( theNbSteps );
+  std::list<double>::const_iterator scale = theScales.begin();
+  double prevScale = 1.0;
+  for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
+  {
+    int      iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
+    int    stDelta = Max( 1, iStep - myScales.size());
+    double scDelta = ( *scale - prevScale ) / stDelta;
+    for ( int iStep = 0; iStep < stDelta; ++iStep )
+    {
+      myScales.push_back( prevScale + scDelta );
+      prevScale = myScales.back();
+    }
+    prevScale = *scale;
+  }
+  theScales.assign( myScales.begin(), myScales.end() );
+}
 
 //================================================================================
 /*!
@@ -6808,8 +6150,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;
@@ -6904,14 +6246,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] );
@@ -6954,8 +6296,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;
@@ -7001,7 +6343,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
@@ -7012,7 +6354,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
   } // loop on elements
 
   if ( editor && editor != this )
-    myLastCreatedElems = editor->myLastCreatedElems;
+    myLastCreatedElems.swap( editor->myLastCreatedElems );
 
   PGroupIDs newGroupIDs;
 
@@ -7023,14 +6365,114 @@ 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. NULL means failure
+ */
+//================================================================================
+
+SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElements,
+                                                      const double       theValue,
+                                                      SMESH_Mesh*        theTgtMesh,
+                                                      const bool         theMakeGroups,
+                                                      const bool         theCopyElements,
+                                                      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::TElemIntPairVec new2OldFaces;
+  SMESH_MeshAlgos::TNodeIntPairVec new2OldNodes;
+  std::unique_ptr< SMDS_Mesh > offsetMesh
+    ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
+                                   theFixSelfIntersection,
+                                   new2OldFaces, new2OldNodes ));
+  if ( offsetMesh->NbElements() == 0 )
+    return PGroupIDs(); // MakeOffset() failed
+
+
+  if ( theTgtMesh == myMesh && !theCopyElements )
+  {
+    // clear the source elements
+    if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+    else                       eIt = SMESHUtils::elemSetIterator( theElements );
+    while ( eIt->more() )
+      meshDS->RemoveFreeElement( eIt->next(), 0 );
+  }
+
+  // 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 )
+    {
+#ifndef _DEBUG_
+      if ( n->NbInverseElements() > 0 )
+#endif
+      {
+        const SMDS_MeshNode* n2 =
+          tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
+        myLastCreatedNodes.push_back( n2 );
+        srcNodes.push_back( meshDS->FindNode( 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( meshDS->FindElement( new2OldFaces[ i ].second ));
+    }
+
+  myLastCreatedElems.swap( tgtEditor.myLastCreatedElems );
+
+  PGroupIDs newGroupIDs;
+  if ( theMakeGroups )
+    newGroupIDs = generateGroups( srcNodes, srcElems, "offset", theTgtMesh, false );
+  else
+    newGroupIDs.reset( new std::list< int > );
+
+  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
  */
 //=======================================================================
 
@@ -7083,30 +6525,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 );
 
@@ -7146,7 +6588,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
           {
             SMDS_MeshGroup & newTopGroup = gOldNew->get<2>()->SMDSGroup();
             newTopGroup.Add( topElem );
-         }
+          }
         }
       }
     } // loop on created elements
@@ -7233,8 +6675,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 ) +
@@ -7247,7 +6688,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() )
       {
@@ -7347,8 +6788,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();
 
@@ -7384,8 +6824,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 )
@@ -7436,7 +6879,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 );
@@ -7624,7 +7067,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();
 
@@ -7942,26 +7385,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;
 };
 
 //=======================================================================
@@ -7970,53 +7442,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 );
     }
   }
 }
@@ -8028,8 +7494,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
@@ -8068,8 +7533,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 );
 }
 
 //=======================================================================
@@ -8130,48 +7595,37 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
   theNodes.push_back( theSecondNode );
 
   const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
-  TIDSortedElemSet foundElems;
+  //TIDSortedElemSet foundElems;
   bool needTheLast = ( theLastNode != 0 );
 
+  vector<const SMDS_MeshNode*> nodes;
+  
   while ( nStart != theLastNode ) {
     if ( nStart == theFirstNode )
       return !needTheLast;
 
-    // find all free border faces sharing form nStart
+    // find all free border faces sharing nStart
 
     list< const SMDS_MeshElement* > curElemList;
     list< const SMDS_MeshNode* >    nStartList;
     SMDS_ElemIteratorPtr invElemIt = nStart->GetInverseElementIterator(SMDSAbs_Face);
     while ( invElemIt->more() ) {
       const SMDS_MeshElement* e = invElemIt->next();
-      if ( e == curElem || foundElems.insert( e ).second ) {
+      //if ( e == curElem || foundElems.insert( e ).second ) // e can encounter twice in border
+      {
         // 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 ];
+        nodes.assign( SMDS_MeshElement::iterator( e->interlacedNodesIterator() ),
+                      SMDS_MeshElement::iterator() );
+        nodes.push_back( nodes[ 0 ]);
+
         // check 2 links
+        int iNode = 0, nbNodes = nodes.size() - 1;
         for ( iNode = 0; iNode < nbNodes; iNode++ )
-          if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
-               (nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
-              ControlFreeBorder( &nodes[ iNode ], e->GetID() ))
+          if ((( nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
+               ( nodes[ iNode + 1] == nStart && nodes[ iNode ] != nIgnore )) &&
+              ( ControlFreeBorder( &nodes[ iNode ], e->GetID() )))
           {
-            nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart ? 1 : 0 )]);
+            nStartList.push_back( nodes[ iNode + ( nodes[ iNode ] == nStart )]);
             curElemList.push_back( e );
           }
       }
@@ -8223,7 +7677,7 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
         else if ( !contNodes[0].empty() && !contNodes[1].empty() ) {
           // choice: clear a worse one
           int iLongest = ( contNodes[0].size() < contNodes[1].size() ? 1 : 0 );
-          int iWorse = ( needTheLast ? 1 - iLongest : iLongest );
+          int   iWorse = ( needTheLast ? 1 - iLongest : iLongest );
           contNodes[ iWorse ].clear();
           contFaces[ iWorse ].clear();
         }
@@ -8231,16 +7685,14 @@ 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
+      //theNodes.pop_back(); // remove nIgnore
       theNodes.pop_back(); // remove nStart
-      theFaces.pop_back(); // remove curElem
-      list< const SMDS_MeshNode* >::iterator nIt = cNL->begin();
-      list< const SMDS_MeshElement* >::iterator fIt = cFL->begin();
-      for ( ; nIt != cNL->end(); nIt++ ) theNodes.push_back( *nIt );
-      for ( ; fIt != cFL->end(); fIt++ ) theFaces.push_back( *fIt );
+      //theFaces.pop_back(); // remove curElem
+      theNodes.splice( theNodes.end(), *cNL );
+      theFaces.splice( theFaces.end(), *cFL );
       return true;
 
     } // several continuations found
@@ -8281,8 +7733,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
                                  const bool           toCreatePolygons,
                                  const bool           toCreatePolyedrs)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  ClearLastCreated();
 
   Sew_Error aResult = SEW_OK;
 
@@ -8422,27 +7873,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;
@@ -8596,6 +8033,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     nIt[0] = nSide[0].begin(); eIt[0] = eSide[0].begin();
     nIt[1] = nSide[1].begin(); eIt[1] = eSide[1].begin();
 
+    // element can be split while iterating on border if it has two edges in the border
+    std::map< const SMDS_MeshElement* , const SMDS_MeshElement* > elemReplaceMap;
+    std::map< const SMDS_MeshElement* , const SMDS_MeshElement* >::iterator elemReplaceMapIt;
+
     TElemOfNodeListMap insertMap;
     TElemOfNodeListMap::iterator insertMapIt;
     // insertMap is
@@ -8643,12 +8084,15 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         const SMDS_MeshNode*    nIns = *nIt [ 1 - intoBord ];
         if ( intoBord == 1 ) {
           // move node of the border to be on a link of elem of the side
-          gp_XYZ p1 (n1->X(), n1->Y(), n1->Z());
-          gp_XYZ p2 (n2->X(), n2->Y(), n2->Z());
+          SMESH_NodeXYZ p1( n1 ), p2( n2 );
           double ratio = du / ( param[ 1 ][ i[1] ] - param[ 1 ][ i[1]-1 ]);
           gp_XYZ p = p2 * ( 1 - ratio ) + p1 * ratio;
           GetMeshDS()->MoveNode( nIns, p.X(), p.Y(), p.Z() );
         }
+        elemReplaceMapIt = elemReplaceMap.find( elem );
+        if ( elemReplaceMapIt != elemReplaceMap.end() )
+          elem = elemReplaceMapIt->second;
+
         insertMapIt = insertMap.find( elem );
         bool  notFound = ( insertMapIt == insertMap.end() );
         bool otherLink = ( !notFound && (*insertMapIt).second.front() != n1 );
@@ -8671,8 +8115,10 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
             UpdateVolumes(n12, n22, nodeList);
           }
           // 3. find an element appeared on n1 and n2 after the insertion
-          insertMap.erase( elem );
-          elem = findAdjacentFace( n1, n2, 0 );
+          insertMap.erase( insertMapIt );
+          const SMDS_MeshElement* elem2 = findAdjacentFace( n1, n2, 0 );
+          elemReplaceMap.insert( std::make_pair( elem, elem2 ));
+          elem = elem2;
         }
         if ( notFound || otherLink ) {
           // add element and nodes of the side into the insertMap
@@ -8705,6 +8151,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
     {
       const SMDS_MeshElement* elem = (*insertMapIt).first;
       list<const SMDS_MeshNode*> & nodeList = (*insertMapIt).second;
+      if ( nodeList.size() < 3 ) continue;
       const SMDS_MeshNode* n1 = nodeList.front(); nodeList.pop_front();
       const SMDS_MeshNode* n2 = nodeList.front(); nodeList.pop_front();
 
@@ -8735,19 +8182,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() );
@@ -8776,7 +8224,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;
@@ -8846,7 +8294,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 );
@@ -8902,48 +8350,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
@@ -9107,7 +8528,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);
@@ -9123,8 +8544,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
@@ -9186,7 +8606,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 );
@@ -9286,7 +8706,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 );
 
@@ -9304,52 +8724,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:
-        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);
-        }
+      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;
     }
@@ -9507,7 +8927,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 );
 
@@ -9727,7 +9147,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 );
@@ -9861,7 +9281,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
@@ -9913,7 +9333,7 @@ void SMESH_MeshEditor::ConvertFromQuadratic(TIDSortedElemSet& theElements)
       }
     }
   }
-  elemIt = elemSetIterator( moreElemsToConvert );
+  elemIt = SMESHUtils::elemSetIterator( moreElemsToConvert );
   removeQuadElem( /*theSm=*/0, elemIt, /*theShapeID=*/0 );
 }
 
@@ -9930,8 +9350,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;
@@ -10207,12 +9626,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;
   }
@@ -10270,20 +9689,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());
       }
     }
@@ -10351,7 +9758,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;
@@ -10362,9 +9769,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);
@@ -11179,16 +10586,19 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
       if ( mesh->GetMeshInfo().NbElements( types[i] ))
       {
         type = types[i];
+        elemIt = mesh->elementsIterator( type );
         break;
       }
-    elemIt = mesh->elementsIterator( type );
   }
   else
   {
-    type = (*theElements.begin())->GetType();
-    elemIt = elemSetIterator( theElements );
+    //type = (*theElements.begin())->GetType();
+    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;
@@ -11197,13 +10607,15 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
   while ( elemIt->more() )
   {
     const SMDS_MeshElement* elem = elemIt->next();
-    if ( elem->GetType() != type )
+    if (( type != SMDSAbs_All && 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 );
   }
 }
 
@@ -11291,7 +10703,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;
@@ -11350,7 +10762,7 @@ bool SMESH_MeshEditor::DoubleNodes( const std::list< int >& theListOfNodes,
     {
       copyPosition( aNode, aNewNode );
       anOldNodeToNewNode[ aNode ] = aNewNode;
-      myLastCreatedNodes.Append( aNewNode );
+      myLastCreatedNodes.push_back( aNewNode );
     }
   }
 
@@ -11385,8 +10797,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
   */
   //================================================================================
 
@@ -11396,8 +10808,7 @@ namespace {
                 const double            theTol)
   {
     gp_XYZ centerXYZ (0, 0, 0);
-    SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
-    while ( aNodeItr->more() )
+    for ( SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); aNodeItr->more(); )
       centerXYZ += SMESH_NodeXYZ( aNodeItr->next() );
 
     gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
@@ -11470,8 +10881,8 @@ bool SMESH_MeshEditor::AffectedElemGroupsInRegion( const TIDSortedElemSet& theEl
   else
   {
     const double aTol = Precision::Confusion();
-    auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
-    auto_ptr<_FaceClassifier>              aFaceClassifier;
+    std::unique_ptr< BRepClass3d_SolidClassifier> bsc3d;
+    std::unique_ptr<_FaceClassifier>              aFaceClassifier;
     if ( theShape.ShapeType() == TopAbs_SOLID )
     {
       bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
@@ -11622,7 +11033,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
@@ -11688,7 +11099,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];
@@ -11696,7 +11107,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
         {
@@ -11759,7 +11170,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);
@@ -11843,7 +11254,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());
           }
@@ -11916,7 +11327,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++ )
@@ -11925,26 +11336,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 )
                       {
-                        gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+                        double *coords = grid->GetPoint( pts[i] );
+                        for ( int j = 0; j < 3; ++j )
+                          values[j] += coords[j] / npts;
+                      }
+                      if ( id == 0 )
+                      {
+                        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]);
                       }
@@ -11986,12 +11402,11 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //MESSAGE(".. Creation of elements: simple junction");
   if (createJointElems)
   {
-    int idg;
     string joints2DName = "joints2D";
-    mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg);
+    mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str());
     SMESHDS_Group *joints2DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints2DName]->GetGroupDS());
     string joints3DName = "joints3D";
-    mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg);
+    mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str());
     SMESHDS_Group *joints3DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints3DName]->GetGroupDS());
 
     itface = faceDomains.begin();
@@ -12019,7 +11434,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         grpname << dom2 << "_" << dom1;
       string namegrp = grpname.str();
       if (!mapOfJunctionGroups.count(namegrp))
-        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
+        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str());
       SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
       if (sgrp)
         sgrp->Add(vol->GetID());
@@ -12052,10 +11467,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       stringstream grpname;
       grpname << "m2j_";
       grpname << 0 << "_" << 0;
-      int idg;
       string namegrp = grpname.str();
       if (!mapOfJunctionGroups.count(namegrp))
-        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg);
+        mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str());
       SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
       if (sgrp)
         sgrp->Add(face->GetID());
@@ -12081,10 +11495,9 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               orderedNodes.push_back( nodeDomains[ nodes[ ino ]][ orderDom[ idom ]]);
         SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
 
-        int idg;
         string namegrp = "jointsMultiples";
         if (!mapOfJunctionGroups.count(namegrp))
-          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
         SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
         if (sgrp)
           sgrp->Add(vol->GetID());
@@ -12133,7 +11546,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);
             }
       }
@@ -12165,7 +11578,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)
         {
@@ -12232,8 +11645,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());
@@ -12242,11 +11654,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
@@ -12343,10 +11755,9 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
         stringstream grpname;
         grpname << "jf_";
         grpname << idom;
-        int idg;
         string namegrp = grpname.str();
         if (!mapOfJunctionGroups.count(namegrp))
-          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+          mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str());
         SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
         if (sgrp)
           sgrp->Add(vol->GetID());
@@ -12354,7 +11765,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;
@@ -12417,10 +11828,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
 
   // --- define groups to build
 
-  int idg; // --- group of SMDS volumes
+  // --- group of SMDS volumes
   string grpvName = groupName;
   grpvName += "_vol";
-  SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str(), idg);
+  SMESH_Group *grp = this->myMesh->AddGroup(SMDSAbs_Volume, grpvName.c_str());
   if (!grp)
   {
     MESSAGE("group not created " << grpvName);
@@ -12428,10 +11839,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(grp->GetGroupDS());
 
-  int idgs; // --- group of SMDS faces on the skin
+  // --- group of SMDS faces on the skin
   string grpsName = groupName;
   grpsName += "_skin";
-  SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str(), idgs);
+  SMESH_Group *grps = this->myMesh->AddGroup(SMDSAbs_Face, grpsName.c_str());
   if (!grps)
   {
     MESSAGE("group not created " << grpsName);
@@ -12439,10 +11850,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrps = dynamic_cast<SMESHDS_Group*>(grps->GetGroupDS());
 
-  int idgi; // --- group of SMDS faces internal (several shapes)
+  // --- group of SMDS faces internal (several shapes)
   string grpiName = groupName;
   grpiName += "_internalFaces";
-  SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str(), idgi);
+  SMESH_Group *grpi = this->myMesh->AddGroup(SMDSAbs_Face, grpiName.c_str());
   if (!grpi)
   {
     MESSAGE("group not created " << grpiName);
@@ -12450,10 +11861,10 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   }
   SMESHDS_Group *sgrpi = dynamic_cast<SMESHDS_Group*>(grpi->GetGroupDS());
 
-  int idgei; // --- group of SMDS faces internal (several shapes)
+  // --- group of SMDS faces internal (several shapes)
   string grpeiName = groupName;
   grpeiName += "_internalEdges";
-  SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str(), idgei);
+  SMESH_Group *grpei = this->myMesh->AddGroup(SMDSAbs_Edge, grpeiName.c_str());
   if (!grpei)
   {
     MESSAGE("group not created " << grpeiName);
@@ -12465,7 +11876,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
 
@@ -12492,7 +11903,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());
       }
     }
@@ -12547,7 +11958,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())
     {
@@ -12566,7 +11977,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;
@@ -12600,14 +12011,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];
@@ -12619,7 +12030,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);
     }
@@ -12654,7 +12065,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];
@@ -12666,9 +12077,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
@@ -12689,7 +12100,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];
@@ -12708,7 +12119,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]);
@@ -12717,7 +12128,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));
           }
         }
       }
@@ -12727,7 +12138,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));
       }
     }
   }
@@ -12746,7 +12157,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;
@@ -12781,7 +12192,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
         {
@@ -12935,7 +12346,7 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
       // add new face based on volume nodes
       if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) )
       {
-        nbExisted++; // face already exsist
+        nbExisted++; // face already exists
       }
       else
       {
@@ -13019,9 +12430,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();
@@ -13102,7 +12513,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 );
@@ -13135,7 +12546,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
         tgtNodes.resize( srcNodes.size() );
         for ( inode = 0; inode < srcNodes.size(); ++inode )
           tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -13146,7 +12557,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
       for ( size_t i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& nodes = missingBndElems[ i ];
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -13198,7 +12609,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
@@ -13209,11 +12620,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
@@ -13221,7 +12632,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();
@@ -13230,7 +12641,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;
@@ -13256,7 +12667,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;
@@ -13264,7 +12675,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;
   }
@@ -13277,482 +12688,3 @@ 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.Append( nPrev );
-    }
-    for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
-    {
-      n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
-      myLastCreatedNodes.Append( n );
-
-      const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
-      myLastCreatedElems.Append( elem );
-      if ( theGroup )
-        theGroup->Add( elem );
-
-      nPrev = n;
-    }
-
-    // return a vector
-
-    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;
-}