Salome HOME
Merge from V6_5_BR 05/06/2012
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index 85a8b912c6c5d29a5516cbad5b0448e908577e1a..e3fbc6602c1db1b06f17eabac1e6fbc201f43374 100644 (file)
@@ -1,40 +1,37 @@
-//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  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
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
 //
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH SMESH : idl implementation based on 'SMESH' unit's classes
+// SMESH SMESH : idl implementation based on 'SMESH' unit's classes
 // File      : SMESH_MeshEditor.cxx
 // Created   : Mon Apr 12 16:10:22 2004
 // Author    : Edward AGAPOV (eap)
-//
-#define CHRONODEF
+
 #include "SMESH_MeshEditor.hxx"
 
 #include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMDS_EdgePosition.hxx"
-#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
-//#include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_MeshGroup.hxx"
 #include "SMDS_LinearEdge.hxx"
 #include "SMDS_Downward.hxx"
 #include "SMESH_OctreeNode.hxx"
 #include "SMESH_subMesh.hxx"
 
+#include <Basics_OCCTVersion.hxx>
+
 #include "utilities.h"
 
 #include <BRepAdaptor_Surface.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepClass3d_SolidClassifier.hxx>
 #include <BRep_Tool.hxx>
 #include <ElCLib.hxx>
 #include <gp_XY.hxx>
 #include <gp_XYZ.hxx>
 
-#include <math.h>
+#include <cmath>
 
 #include <map>
 #include <set>
 #include <numeric>
 #include <limits>
 #include <algorithm>
+#include <sstream>
 
 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
 
@@ -155,6 +156,12 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
         else           e = mesh->AddFace      (node[0], node[1], node[2], node[3],
                                                node[4], node[5], node[6], node[7] );
       }
+      else if (nbnode == 9) {
+        if ( ID >= 1 ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
+                                               node[4], node[5], node[6], node[7], node[8], ID);
+        else           e = mesh->AddFace      (node[0], node[1], node[2], node[3],
+                                               node[4], node[5], node[6], node[7], node[8] );
+      }
     } else {
       if ( ID >= 1 ) e = mesh->AddPolygonalFaceWithID(node, ID);
       else           e = mesh->AddPolygonalFace      (node    );
@@ -193,6 +200,14 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
                                                  node[4], node[5], node[6], node[7],
                                                  node[8], node[9] );
       }
+      else if (nbnode == 12) {
+        if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                                 node[4], node[5], node[6], node[7],
+                                                 node[8], node[9], node[10], node[11], ID);
+        else           e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                                 node[4], node[5], node[6], node[7],
+                                                 node[8], node[9], node[10], node[11] );
+      }
       else if (nbnode == 13) {
         if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
                                                  node[4], node[5], node[6], node[7],
@@ -225,6 +240,22 @@ SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
                                                  node[12],node[13],node[14],node[15],
                                                  node[16],node[17],node[18],node[19] );
       }
+      else if (nbnode == 27) {
+        if ( ID >= 1 ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                                 node[4], node[5], node[6], node[7],
+                                                 node[8], node[9], node[10],node[11],
+                                                 node[12],node[13],node[14],node[15],
+                                                 node[16],node[17],node[18],node[19],
+                                                 node[20],node[21],node[22],node[23],
+                                                 node[24],node[25],node[26], ID);
+        else           e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                                 node[4], node[5], node[6], node[7],
+                                                 node[8], node[9], node[10],node[11],
+                                                 node[12],node[13],node[14],node[15],
+                                                 node[16],node[17],node[18],node[19],
+                                                 node[20],node[21],node[22],node[23],
+                                                 node[24],node[25],node[26] );
+      }
     }
     break;
 
@@ -364,45 +395,55 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
   if ( aMesh->ShapeToMesh().IsNull() )
     return 0;
 
-  if ( theElem->GetType() == SMDSAbs_Node )
-    {
-      int aShapeID = theElem->getshapeId();
-      if (aShapeID <= 0)
-        return 0;
-      else
-        return aShapeID;
-    }
-
-  TopoDS_Shape aShape; // the shape a node is on
-  SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
-  while ( nodeIt->more() ) {
-    const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-    int aShapeID = node->getshapeId();
-    if (aShapeID > 0) {
-      SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID );
-      if ( sm ) {
-        if ( sm->Contains( theElem ))
-          return aShapeID;
-        if ( aShape.IsNull() )
-          aShape = aMesh->IndexToShape( aShapeID );
-      }
-      else {
-        //MESSAGE ( "::FindShape() No SubShape for aShapeID " << aShapeID );
+  int aShapeID = theElem->getshapeId();
+  if ( aShapeID < 1 )
+    return 0;
+
+  if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ))
+    if ( sm->Contains( theElem ))
+      return aShapeID;
+
+  if ( theElem->GetType() == SMDSAbs_Node ) {
+    MESSAGE( ":( Error: invalid myShapeId of node " << theElem->GetID() );
+  }
+  else {
+    MESSAGE( ":( Error: invalid myShapeId of element " << theElem->GetID() );
+  }
+
+  TopoDS_Shape aShape; // the shape a node of theElem is on
+  if ( theElem->GetType() != SMDSAbs_Node )
+  {
+    SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
+    while ( nodeIt->more() ) {
+      const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+      if ((aShapeID = node->getshapeId()) > 0) {
+        if ( SMESHDS_SubMesh * sm = aMesh->MeshElements( aShapeID ) ) {
+          if ( sm->Contains( theElem ))
+            return aShapeID;
+          if ( aShape.IsNull() )
+            aShape = aMesh->IndexToShape( aShapeID );
+        }
       }
     }
   }
 
   // None of nodes is on a proper shape,
   // find the shape among ancestors of aShape on which a node is
-  if ( aShape.IsNull() ) {
-    //MESSAGE ("::FindShape() - NONE node is on shape")
-    return 0;
+  if ( !aShape.IsNull() ) {
+    TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
+    for ( ; ancIt.More(); ancIt.Next() ) {
+      SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
+      if ( sm && sm->Contains( theElem ))
+        return aMesh->ShapeToIndex( ancIt.Value() );
+    }
   }
-  TopTools_ListIteratorOfListOfShape ancIt( GetMesh()->GetAncestors( aShape ));
-  for ( ; ancIt.More(); ancIt.Next() ) {
-    SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
-    if ( sm && sm->Contains( theElem ))
-      return aMesh->ShapeToIndex( ancIt.Value() );
+  else
+  {
+    const map<int,SMESHDS_SubMesh*>& id2sm = GetMeshDS()->SubMeshes();
+    map<int,SMESHDS_SubMesh*>::const_iterator id_sm = id2sm.begin();
+    for ( ; id_sm != id2sm.end(); ++id_sm )
+      if ( id_sm->second->Contains( theElem ))
+        return id_sm->first;
   }
 
   //MESSAGE ("::FindShape() - SHAPE NOT FOUND")
@@ -444,6 +485,25 @@ static void ShiftNodesQuadTria(const SMDS_MeshNode* aNodes[])
   aNodes[5] = nd2;
 }
 
+//=======================================================================
+//function : edgeConnectivity
+//purpose  : auxilary 
+//           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;
+}
+
+
 //=======================================================================
 //function : GetNodesFromTwoTria
 //purpose  : auxilary
@@ -1033,15 +1093,11 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     const SMDS_MeshElement* elem = *itElem;
     if ( !elem || elem->GetType() != SMDSAbs_Face )
       continue;
-    if ( elem->NbNodes() != ( elem->IsQuadratic() ? 8 : 4 ))
+    if ( elem->NbCornerNodes() != 4 )
       continue;
 
     // retrieve element nodes
-    const SMDS_MeshNode* aNodes [8];
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    int i = 0;
-    while ( itN->more() )
-      aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+    vector< const SMDS_MeshNode* > aNodes( elem->begin_nodes(), elem->end_nodes() );
 
     // compare two sets of possible triangles
     double aBadRate1, aBadRate2; // to what extent a set is bad
@@ -1060,6 +1116,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     if( !elem->IsQuadratic() ) {
 
       // split liner quadrangle
+
       if ( aBadRate1 <= aBadRate2 ) {
         // tr1 + tr2 is better
         newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
@@ -1088,59 +1145,49 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
             helper.SetSubShape( shape );
         }
       }
-      // get elem nodes
-      const SMDS_MeshNode* aNodes [8];
-      const SMDS_MeshNode* inFaceNode = 0;
-      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-      int i = 0;
-      while ( itN->more() ) {
-        aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
-        if ( !inFaceNode && helper.GetNodeUVneedInFaceNode() &&
-             aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
-        {
-          inFaceNode = aNodes[ i-1 ];
-        }
-      }
       // find middle point for (0,1,2,3)
       // and create a node in this point;
-      gp_XYZ p( 0,0,0 );
-      if ( surface.IsNull() ) {
-        for(i=0; i<4; i++)
-          p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
-        p /= 4;
+      const SMDS_MeshNode* newN = 0;
+      if ( aNodes.size() == 9 )
+      {
+        // SMDSEntity_BiQuad_Quadrangle
+        newN = aNodes.back();
       }
-      else {
-        TopoDS_Face face = TopoDS::Face( helper.GetSubShape() );
-        gp_XY uv( 0,0 );
-        for(i=0; i<4; i++)
-          uv += helper.GetNodeUV( face, aNodes[i], inFaceNode );
-        uv /= 4.;
-        p = surface->Value( uv.X(), uv.Y() ).XYZ();
+      else
+      {
+        gp_XYZ p( 0,0,0 );
+        if ( surface.IsNull() )
+        {
+          for ( int i = 0; i < 4; i++ )
+            p += gp_XYZ(aNodes[i]->X(), aNodes[i]->Y(), aNodes[i]->Z() );
+          p /= 4;
+        }
+        else
+        {
+          const SMDS_MeshNode* inFaceNode = 0;
+          if ( helper.GetNodeUVneedInFaceNode() )
+            for ( size_t i = 0; i < aNodes.size() && !inFaceNode; ++i )
+              if ( aNodes[ i ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
+                inFaceNode = aNodes[ i ];
+
+          TopoDS_Face face = TopoDS::Face( helper.GetSubShape() );
+          gp_XY uv( 0,0 );
+          for ( int i = 0; i < 4; i++ )
+            uv += helper.GetNodeUV( face, aNodes[i], inFaceNode );
+          uv /= 4.;
+          p = surface->Value( uv.X(), uv.Y() ).XYZ();
+        }
+        newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
+        myLastCreatedNodes.Append(newN);
       }
-      const SMDS_MeshNode* newN = aMesh->AddNode( p.X(), p.Y(), p.Z() );
-      myLastCreatedNodes.Append(newN);
-
       // create a new element
-      const SMDS_MeshNode* N[6];
       if ( aBadRate1 <= aBadRate2 ) {
-        N[0] = aNodes[0];
-        N[1] = aNodes[1];
-        N[2] = aNodes[2];
-        N[3] = aNodes[4];
-        N[4] = aNodes[5];
-        N[5] = newN;
         newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
                                   aNodes[6], aNodes[7], newN );
         newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
                                   newN,      aNodes[4], aNodes[5] );
       }
       else {
-        N[0] = aNodes[1];
-        N[1] = aNodes[2];
-        N[2] = aNodes[3];
-        N[3] = aNodes[5];
-        N[4] = aNodes[6];
-        N[5] = newN;
         newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
                                   aNodes[7], aNodes[4], newN );
         newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
@@ -1380,6 +1427,7 @@ namespace
       {
       case SMDSEntity_Hexa:
       case SMDSEntity_Quad_Hexa:
+      case SMDSEntity_TriQuad_Hexa:
         if ( theMethodFlags == SMESH_MeshEditor::HEXA_TO_5 )
           connVariants = theHexTo5, nbTet = 5;
         else
@@ -1421,13 +1469,15 @@ namespace
       // each facet of a volume is split into triangles and
       // each of triangles and a volume barycenter form a tetrahedron.
 
+      const bool isHex27 = ( vol.Element()->GetEntityType() == SMDSEntity_TriQuad_Hexa );
+
       int* connectivity = new int[ maxTetConnSize + 1 ];
       method._connectivity = connectivity;
       method._ownConn = true;
-      method._baryNode = true;
+      method._baryNode = !isHex27; // to create central node or not
 
       int connSize = 0;
-      int baryCenInd = vol.NbNodes();
+      int baryCenInd = vol.NbNodes() - int( isHex27 );
       for ( int iF = 0; iF < vol.NbFaces(); ++iF )
       {
         const int nbNodes = vol.NbFaceNodes( iF ) / iQ;
@@ -1452,14 +1502,17 @@ namespace
           const SMDS_MeshNode** nodes = vol.GetFaceNodes( iF );
           int nbVariants = ( nbNodes == 4 ? 2 : nbNodes );
           for ( int iVar = 0; iVar < nbVariants; ++iVar, ++iCommon )
+          {
+            double badness = 0;
             for ( int iLast = iCommon+2; iLast < iCommon+nbNodes; ++iLast )
             {
               SMDS_FaceOfNodes tria ( nodes[ iQ*( iCommon         )],
                                       nodes[ iQ*((iLast-1)%nbNodes)],
                                       nodes[ iQ*((iLast  )%nbNodes)]);
-              double badness = getBadRate( &tria, aspectRatio );
-              badness2iCommon.insert( make_pair( badness, iCommon ));
+              badness += getBadRate( &tria, aspectRatio );
             }
+            badness2iCommon.insert( make_pair( badness, iCommon ));
+          }
           // use iCommon with lowest badness
           iCommon = badness2iCommon.begin()->second;
         }
@@ -1470,8 +1523,17 @@ namespace
         int nbTet = nbNodes - 2;
         if ( is24TetMode && nbNodes > 3 && triaSplits.empty())
         {
-          method._faceBaryNode.insert( make_pair( iF, (const SMDS_MeshNode*)0 ));
-          int faceBaryCenInd = baryCenInd + method._faceBaryNode.size();
+          int faceBaryCenInd;
+          if ( isHex27 )
+          {
+            faceBaryCenInd = vol.GetCenterNodeIndex( iF );
+            method._faceBaryNode[ iF ] = vol.GetNodes()[ faceBaryCenInd ];
+          }
+          else
+          {
+            method._faceBaryNode[ iF ] = 0;
+            faceBaryCenInd = baryCenInd + method._faceBaryNode.size();
+          }
           nbTet = nbNodes;
           for ( int i = 0; i < nbTet; ++i )
           {
@@ -1496,9 +1558,13 @@ namespace
           }
         }
         method._nbTetra += nbTet;
-      }
+
+      } // loop on volume faces
+
       connectivity[ connSize++ ] = -1;
-    }
+
+    } // end of generic solution
+
     return method;
   }
   //================================================================================
@@ -1517,16 +1583,18 @@ namespace
     while ( volIt1->more() )
     {
       const SMDS_MeshElement* v = volIt1->next();
-      if ( v->GetEntityType() != ( v->IsQuadratic() ? SMDSEntity_Quad_Tetra : SMDSEntity_Tetra ))
+      SMDSAbs_EntityType type = v->GetEntityType();
+      if ( type != SMDSEntity_Tetra && type != SMDSEntity_Quad_Tetra )
         continue;
-      SMDS_ElemIteratorPtr volIt2 = n2->GetInverseElementIterator(SMDSAbs_Volume);
-      while ( volIt2->more() )
-        if ( v != volIt2->next() )
-          continue;
-      SMDS_ElemIteratorPtr volIt3 = n3->GetInverseElementIterator(SMDSAbs_Volume);
-      while ( volIt3->more() )
-        if ( v == volIt3->next() )
-          return true;
+      if ( type == SMDSEntity_Quad_Tetra && v->GetNodeIndex( n1 ) > 3 )
+        continue; // medium node not allowed
+      const int ind2 = v->GetNodeIndex( n2 );
+      if ( ind2 < 0 || 3 < ind2 )
+        continue;
+      const int ind3 = v->GetNodeIndex( n3 );
+      if ( ind3 < 0 || 3 < ind3 )
+        continue;
+      return true;
     }
     return false;
   }
@@ -1537,7 +1605,7 @@ namespace
    */
   //=======================================================================
 
-  struct TVolumeFaceKey: pair< int, pair< int, int> >
+  struct TVolumeFaceKey: pair< pair< int, int>, pair< int, int> >
   {
     TVolumeFaceKey( SMDS_VolumeTool& vol, int iF )
     {
@@ -1548,16 +1616,17 @@ namespace
       for ( int i = 0; i < nbNodes; i += iQ )
         sortedNodes.insert( fNodes[i] );
       TIDSortedNodeSet::iterator n = sortedNodes.begin();
-      first = (*(n++))->GetID();
-      second.first = (*(n++))->GetID();
-      second.second = (*(n++))->GetID();
+      first.first   = (*(n++))->GetID();
+      first.second  = (*(n++))->GetID();
+      second.first  = (*(n++))->GetID();
+      second.second = ( sortedNodes.size() > 3 ) ? (*(n++))->GetID() : 0;
     }
   };
 } // namespace
 
 //=======================================================================
 //function : SplitVolumesIntoTetra
-//purpose  : Split volumic elements into tetrahedra.
+//purpose  : Split volume elements into tetrahedra.
 //=======================================================================
 
 void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
@@ -1582,11 +1651,13 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
   TIDSortedElemSet::const_iterator elem = theElems.begin();
   for ( ; elem != theElems.end(); ++elem )
   {
+    if ( (*elem)->GetType() != SMDSAbs_Volume )
+      continue;
     SMDSAbs_EntityType geomType = (*elem)->GetEntityType();
-    if ( geomType <= SMDSEntity_Quad_Tetra )
-      continue; // tetra or face or ...
+    if ( geomType == SMDSEntity_Tetra || geomType == SMDSEntity_Quad_Tetra )
+      continue;
 
-    if ( !volTool.Set( *elem )) continue; // not volume? strange...
+    if ( !volTool.Set( *elem, /*ignoreCentralNodes=*/false )) continue; // strange...
 
     TSplitMethod splitMethod = getSplitMethod( volTool, theMethodFlags );
     if ( splitMethod._nbTetra < 1 ) continue;
@@ -1606,8 +1677,9 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
       for ( int iF = 0; iF < volTool.NbFaces(); ++iF )
       {
         const SMDS_MeshNode** fNodes = volTool.GetFaceNodes( iF );
-        for ( int iN = 0; iN < volTool.NbFaceNodes( iF ); iN += iQ )
-          helper.AddTLinkNode( fNodes[iF], fNodes[iF+2], fNodes[iF+1] );
+        int nbN = volTool.NbFaceNodes( iF ) - bool( volTool.GetCenterNodeIndex(iF) > 0 );
+        for ( int iN = 0; iN < nbN; iN += iQ )
+          helper.AddTLinkNode( fNodes[iN], fNodes[iN+2], fNodes[iN+1] );
       }
       helper.SetIsQuadratic( true );
     }
@@ -1617,6 +1689,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
       helper.SetIsQuadratic( false );
     }
     vector<const SMDS_MeshNode*> nodes( (*elem)->begin_nodes(), (*elem)->end_nodes() );
+    helper.SetElementsOnShape( true );
     if ( splitMethod._baryNode )
     {
       // make a node at barycenter
@@ -1633,7 +1706,7 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
       {
         map< TVolumeFaceKey, const SMDS_MeshNode* >::iterator f_n =
           volFace2BaryNode.insert
-          ( make_pair( TVolumeFaceKey( volTool,iF_n->first ), (const SMDS_MeshNode*)0) ).first;
+          ( make_pair( TVolumeFaceKey( volTool,iF_n->first ), iF_n->second )).first;
         if ( !f_n->second )
         {
           volTool.GetFaceBaryCenter( iF_n->first, bc[0], bc[1], bc[2] );
@@ -1644,7 +1717,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
     }
 
     // make tetras
-    helper.SetElementsOnShape( true );
     vector<const SMDS_MeshElement* > tetras( splitMethod._nbTetra ); // splits of a volume
     const int* tetConn = splitMethod._connectivity;
     for ( int i = 0; i < splitMethod._nbTetra; ++i, tetConn += 4 )
@@ -1665,24 +1737,34 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
 
       // find an existing face
       vector<const SMDS_MeshNode*> fNodes( volTool.GetFaceNodes( iF ),
-                                           volTool.GetFaceNodes( iF ) + nbNodes*iQ );
-      while ( const SMDS_MeshElement* face = GetMeshDS()->FindFace( fNodes ))
+                                           volTool.GetFaceNodes( iF ) + volTool.NbFaceNodes( iF ));
+      while ( const SMDS_MeshElement* face = GetMeshDS()->FindElement( fNodes, SMDSAbs_Face,
+                                                                       /*noMedium=*/false))
       {
         // make triangles
         helper.SetElementsOnShape( false );
         vector< const SMDS_MeshElement* > triangles;
 
+        // find submesh to add new triangles in
+        if ( !fSubMesh || !fSubMesh->Contains( face ))
+        {
+          int shapeID = FindShape( face );
+          fSubMesh = GetMeshDS()->MeshElements( shapeID );
+        }
         map<int, const SMDS_MeshNode*>::iterator iF_n = splitMethod._faceBaryNode.find(iF);
         if ( iF_n != splitMethod._faceBaryNode.end() )
         {
           for ( int iN = 0; iN < nbNodes*iQ; iN += iQ )
           {
             const SMDS_MeshNode* n1 = fNodes[iN];
-            const SMDS_MeshNode *n2 = fNodes[(iN+iQ)%nbNodes*iQ];
+            const SMDS_MeshNode *n2 = fNodes[(iN+iQ)%(nbNodes*iQ)];
             const SMDS_MeshNode *n3 = iF_n->second;
             if ( !volTool.IsFaceExternal( iF ))
               swap( n2, n3 );
             triangles.push_back( helper.AddFace( n1,n2,n3 ));
+
+            if ( fSubMesh && n3->getshapeId() < 1 )
+              fSubMesh->AddNode( n3 );
           }
         }
         else
@@ -1721,12 +1803,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
                                                  volNodes[ facet->_n3 ]));
           }
         }
-        // find submesh to add new triangles in
-        if ( !fSubMesh || !fSubMesh->Contains( face ))
-        {
-          int shapeID = FindShape( face );
-          fSubMesh = GetMeshDS()->MeshElements( shapeID );
-        }
         for ( int i = 0; i < triangles.size(); ++i )
         {
           if ( !triangles[i] ) continue;
@@ -1742,6 +1818,13 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
 
     GetMeshDS()->RemoveFreeElement( *elem, subMesh, /*fromGroups=*/false );
 
+    if ( geomType == SMDSEntity_TriQuad_Hexa )
+    {
+      // remove medium nodes that could become free
+      for ( int i = 20; i < volTool.NbNodes(); ++i )
+        if ( volNodes[i]->NbInverseElements() == 0 )
+          GetMeshDS()->RemoveNode( volNodes[i] );
+    }
   } // loop on volumes to split
 
   myLastCreatedNodes = newNodes;
@@ -1947,26 +2030,13 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
       // create a new element
       const SMDS_MeshElement* newElem1 = 0;
       const SMDS_MeshElement* newElem2 = 0;
-      const SMDS_MeshNode* N[6];
       if ( the13Diag ) {
-        N[0] = aNodes[0];
-        N[1] = aNodes[1];
-        N[2] = aNodes[2];
-        N[3] = aNodes[4];
-        N[4] = aNodes[5];
-        N[5] = newN;
         newElem1 = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
                                   aNodes[6], aNodes[7], newN );
         newElem2 = aMesh->AddFace(aNodes[2], aNodes[0], aNodes[1],
                                   newN,      aNodes[4], aNodes[5] );
       }
       else {
-        N[0] = aNodes[1];
-        N[1] = aNodes[2];
-        N[2] = aNodes[3];
-        N[3] = aNodes[5];
-        N[4] = aNodes[6];
-        N[5] = newN;
         newElem1 = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
                                   aNodes[7], aNodes[4], newN );
         newElem2 = aMesh->AddFace(aNodes[3], aNodes[1], aNodes[2],
@@ -1999,7 +2069,7 @@ double getAngle(const SMDS_MeshElement * tr1,
                 const SMDS_MeshNode *    n1,
                 const SMDS_MeshNode *    n2)
 {
-  double angle = 2*PI; // bad angle
+  double angle = 2. * M_PI; // bad angle
 
   // get normals
   SMESH::Controls::TSequenceOfXYZ P1, P2;
@@ -2841,8 +2911,13 @@ static bool getClosestUV (Extrema_GenExtPS& projector,
   if ( projector.IsDone() ) {
     double u, v, minVal = DBL_MAX;
     for ( int i = projector.NbExt(); i > 0; i-- )
+#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
+      if ( projector.SquareDistance( i ) < minVal ) {
+        minVal = projector.SquareDistance( i );
+#else
       if ( projector.Value( i ) < minVal ) {
         minVal = projector.Value( i );
+#endif
         projector.Point( i ).Parameter( u, v );
       }
     result.SetCoord( u, v );
@@ -2917,7 +2992,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
     Handle(Geom_Surface) surface;
     SMESHDS_SubMesh* faceSubMesh = 0;
     TopoDS_Face face;
-    double fToler2 = 0, vPeriod = 0., uPeriod = 0., f,l;
+    double fToler2 = 0, f,l;
     double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
     bool isUPeriodic = false, isVPeriodic = false;
     if ( *fId ) {
@@ -2928,10 +3003,10 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
       fToler2 *= fToler2 * 10.;
       isUPeriodic = surface->IsUPeriodic();
       if ( isUPeriodic )
-        vPeriod = surface->UPeriod();
+        surface->UPeriod();
       isVPeriodic = surface->IsVPeriodic();
       if ( isVPeriodic )
-        uPeriod = surface->VPeriod();
+        surface->VPeriod();
       surface->Bounds( u1, u2, v1, v2 );
     }
     // ---------------------------------------------------------
@@ -3103,35 +3178,27 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
     // fix nodes on mesh boundary
 
     if ( checkBoundaryNodes ) {
-      map< NLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
-      map< NLink, int >::iterator link_nb;
+      map< SMESH_TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
+      map< SMESH_TLink, int >::iterator link_nb;
       // put all elements links to linkNbMap
       list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
       for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
         const SMDS_MeshElement* elem = (*elemIt);
-        int nbn =  elem->NbNodes();
-        if(elem->IsQuadratic())
-          nbn = nbn/2;
+        int nbn =  elem->NbCornerNodes();
         // loop on elem links: insert them in linkNbMap
-        const SMDS_MeshNode* curNode, *prevNode = elem->GetNodeWrap( nbn );
         for ( int iN = 0; iN < nbn; ++iN ) {
-          curNode = elem->GetNode( iN );
-          NLink link;
-          if ( curNode < prevNode ) link = make_pair( curNode , prevNode );
-          else                      link = make_pair( prevNode , curNode );
-          prevNode = curNode;
-          link_nb = linkNbMap.find( link );
-          if ( link_nb == linkNbMap.end() )
-            linkNbMap.insert( make_pair ( link, 1 ));
-          else
-            link_nb->second++;
+          const SMDS_MeshNode* n1 = elem->GetNode( iN );
+          const SMDS_MeshNode* n2 = elem->GetNode(( iN+1 ) % nbn);
+          SMESH_TLink link( n1, n2 );
+          link_nb = linkNbMap.insert( make_pair( link, 0 )).first;
+          link_nb->second++;
         }
       }
       // remove nodes that are in links encountered only once from setMovableNodes
       for ( link_nb = linkNbMap.begin(); link_nb != linkNbMap.end(); ++link_nb ) {
         if ( link_nb->second == 1 ) {
-          setMovableNodes.erase( link_nb->first.first );
-          setMovableNodes.erase( link_nb->first.second );
+          setMovableNodes.erase( link_nb->first.node1() );
+          setMovableNodes.erase( link_nb->first.node2() );
         }
       }
     }
@@ -3376,30 +3443,22 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
 //function : isReverse
 //purpose  : Return true if normal of prevNodes is not co-directied with
 //           gp_Vec(prevNodes[iNotSame],nextNodes[iNotSame]).
-//           iNotSame is where prevNodes and nextNodes are different
+//           iNotSame is where prevNodes and nextNodes are different.
+//           If result is true then future volume orientation is OK
 //=======================================================================
 
-static bool isReverse(vector<const SMDS_MeshNode*> prevNodes,
-                      vector<const SMDS_MeshNode*> nextNodes,
-                      const int            nbNodes,
-                      const int            iNotSame)
+static bool isReverse(const SMDS_MeshElement*             face,
+                      const vector<const SMDS_MeshNode*>& prevNodes,
+                      const vector<const SMDS_MeshNode*>& nextNodes,
+                      const int                           iNotSame)
 {
-  int iBeforeNotSame = ( iNotSame == 0 ? nbNodes - 1 : iNotSame - 1 );
-  int iAfterNotSame  = ( iNotSame + 1 == nbNodes ? 0 : iNotSame + 1 );
-
-  const SMDS_MeshNode* nB = prevNodes[ iBeforeNotSame ];
-  const SMDS_MeshNode* nA = prevNodes[ iAfterNotSame ];
-  const SMDS_MeshNode* nP = prevNodes[ iNotSame ];
-  const SMDS_MeshNode* nN = nextNodes[ iNotSame ];
-
-  gp_Pnt pB ( nB->X(), nB->Y(), nB->Z() );
-  gp_Pnt pA ( nA->X(), nA->Y(), nA->Z() );
-  gp_Pnt pP ( nP->X(), nP->Y(), nP->Z() );
-  gp_Pnt pN ( nN->X(), nN->Y(), nN->Z() );
 
-  gp_Vec vB ( pP, pB ), vA ( pP, pA ), vN ( pP, pN );
+  SMESH_TNodeXYZ pP = prevNodes[ iNotSame ];
+  SMESH_TNodeXYZ pN = nextNodes[ iNotSame ];
+  gp_XYZ extrDir( pN - pP ), faceNorm;
+  SMESH_Algo::FaceNormal( face, faceNorm, /*normalized=*/false );
 
-  return (vA ^ vB) * vN < 0.0;
+  return faceNorm * extrDir < 0.0;
 }
 
 //=======================================================================
@@ -3422,305 +3481,294 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
   //MESSAGE("sweepElement " << nbSteps);
   SMESHDS_Mesh* aMesh = GetMeshDS();
 
+  const int           nbNodes = elem->NbNodes();          
+  const int         nbCorners = elem->NbCornerNodes();
+  SMDSAbs_EntityType baseType = elem->GetEntityType(); /* it can change in case of 
+                                                          polyhedron creation !!! */
   // Loop on elem nodes:
   // find new nodes and detect same nodes indices
-  int nbNodes = elem->NbNodes();
   vector < list< const SMDS_MeshNode* >::const_iterator > itNN( nbNodes );
   vector<const SMDS_MeshNode*> prevNod( nbNodes );
   vector<const SMDS_MeshNode*> nextNod( nbNodes );
   vector<const SMDS_MeshNode*> midlNod( nbNodes );
 
-  int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
+  int iNode, nbSame = 0, nbDouble = 0, iNotSameNode = 0;
   vector<int> sames(nbNodes);
-  vector<bool> issimple(nbNodes);
+  vector<bool> isSingleNode(nbNodes);
 
   for ( iNode = 0; iNode < nbNodes; iNode++ ) {
-    TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ];
-    const SMDS_MeshNode*                 node         = nnIt->first;
+    TNodeOfNodeListMapItr                        nnIt = newNodesItVec[ iNode ];
+    const SMDS_MeshNode*                         node = nnIt->first;
     const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second;
-    if ( listNewNodes.empty() ) {
+    if ( listNewNodes.empty() )
       return;
-    }
-
-    issimple[iNode] = (listNewNodes.size()==nbSteps); // is node medium
 
-    itNN[ iNode ] = listNewNodes.begin();
+    itNN   [ iNode ] = listNewNodes.begin();
     prevNod[ iNode ] = node;
     nextNod[ iNode ] = listNewNodes.front();
-    if( !elem->IsQuadratic() || !issimple[iNode] ) {
-      if ( prevNod[ iNode ] != nextNod [ iNode ])
-        iNotSameNode = iNode;
-      else {
-        iSameNode = iNode;
-        //nbSame++;
+
+    isSingleNode[iNode] = (listNewNodes.size()==nbSteps); /* medium node of quadratic or
+                                                             corner node of linear */
+    if ( prevNod[ iNode ] != nextNod [ iNode ])
+      nbDouble += !isSingleNode[iNode];
+
+    if( iNode < nbCorners ) { // check corners only
+      if ( prevNod[ iNode ] == nextNod [ iNode ])
         sames[nbSame++] = iNode;
-      }
+      else
+        iNotSameNode = iNode;
     }
   }
 
-  //cerr<<"  nbSame = "<<nbSame<<endl;
   if ( nbSame == nbNodes || nbSame > 2) {
     MESSAGE( " Too many same nodes of element " << elem->GetID() );
-    //INFOS( " Too many same nodes of element " << elem->GetID() );
     return;
   }
 
-  //  if( elem->IsQuadratic() && nbSame>0 ) {
-  //    MESSAGE( "Can not rotate quadratic element " << elem->GetID() );
-  //    return;
-  //  }
-
-  int iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
-  int nbBaseNodes = ( elem->IsQuadratic() ? nbNodes/2 : nbNodes );
-  if ( nbSame > 0 ) {
-    iBeforeSame = ( iSameNode == 0 ? nbBaseNodes - 1 : iSameNode - 1 );
-    iAfterSame  = ( iSameNode + 1 == nbBaseNodes ? 0 : iSameNode + 1 );
-    iOpposSame  = ( iSameNode - 2 < 0  ? iSameNode + 2 : iSameNode - 2 );
+  if ( elem->GetType() == SMDSAbs_Face && !isReverse( elem, prevNod, nextNod, iNotSameNode ))
+  {
+    // fix nodes order to have bottom normal external
+    if ( baseType == SMDSEntity_Polygon )
+    {
+      std::reverse( itNN.begin(), itNN.end() );
+      std::reverse( prevNod.begin(), prevNod.end() );
+      std::reverse( midlNod.begin(), midlNod.end() );
+      std::reverse( nextNod.begin(), nextNod.end() );
+      std::reverse( isSingleNode.begin(), isSingleNode.end() );
+    }
+    else
+    {
+      const vector<int>& ind = SMDS_MeshCell::reverseSmdsOrder( baseType );
+      SMDS_MeshCell::applyInterlace( ind, itNN );
+      SMDS_MeshCell::applyInterlace( ind, prevNod );
+      SMDS_MeshCell::applyInterlace( ind, nextNod );
+      SMDS_MeshCell::applyInterlace( ind, midlNod );
+      SMDS_MeshCell::applyInterlace( ind, isSingleNode );
+      if ( nbSame > 0 )
+      {
+        sames[nbSame] = iNotSameNode;
+        for ( int j = 0; j <= nbSame; ++j )
+          for ( size_t i = 0; i < ind.size(); ++i )
+            if ( ind[i] == sames[j] )
+            {
+              sames[j] = i;
+              break;
+            }
+        iNotSameNode = sames[nbSame];
+      }
+    }
   }
 
-  //if(nbNodes==8)
-  //cout<<" prevNod[0]="<< prevNod[0]<<" prevNod[1]="<< prevNod[1]
-  //    <<" prevNod[2]="<< prevNod[2]<<" prevNod[3]="<< prevNod[4]
-  //    <<" prevNod[4]="<< prevNod[4]<<" prevNod[5]="<< prevNod[5]
-  //    <<" prevNod[6]="<< prevNod[6]<<" prevNod[7]="<< prevNod[7]<<endl;
-
-  // check element orientation
-  int i0 = 0, i2 = 2;
-  if ( nbNodes > 2 && !isReverse( prevNod, nextNod, nbNodes, iNotSameNode )) {
-    //MESSAGE("Reversed elem " << elem );
-    i0 = 2;
-    i2 = 0;
-    if ( nbSame > 0 )
-      std::swap( iBeforeSame, iAfterSame );
+  int iSameNode = 0, iBeforeSame = 0, iAfterSame = 0, iOpposSame = 0;
+  if ( nbSame > 0 ) {
+    iSameNode    = sames[ nbSame-1 ];
+    iBeforeSame  = ( iSameNode + nbCorners - 1 ) % nbCorners;
+    iAfterSame   = ( iSameNode + 1 ) % nbCorners;
+    iOpposSame   = ( iSameNode - 2 < 0  ? iSameNode + 2 : iSameNode - 2 );
   }
 
   // make new elements
-  const SMDS_MeshElement* lastElem = elem;
-  for (int iStep = 0; iStep < nbSteps; iStep++ ) {
+  for (int iStep = 0; iStep < nbSteps; iStep++ )
+  {
     // get next nodes
-    for ( iNode = 0; iNode < nbNodes; iNode++ ) {
-      if(issimple[iNode]) {
-        nextNod[ iNode ] = *itNN[ iNode ];
-        itNN[ iNode ]++;
-      }
-      else {
-        if( elem->GetType()==SMDSAbs_Node ) {
-          // we have to use two nodes
-          midlNod[ iNode ] = *itNN[ iNode ];
-          itNN[ iNode ]++;
-          nextNod[ iNode ] = *itNN[ iNode ];
-          itNN[ iNode ]++;
-        }
-        else if(!elem->IsQuadratic() || lastElem->IsMediumNode(prevNod[iNode]) ) {
-          // we have to use each second node
-          //itNN[ iNode ]++;
-          nextNod[ iNode ] = *itNN[ iNode ];
-          itNN[ iNode ]++;
-        }
-        else {
-          // we have to use two nodes
-          midlNod[ iNode ] = *itNN[ iNode ];
-          itNN[ iNode ]++;
-          nextNod[ iNode ] = *itNN[ iNode ];
-          itNN[ iNode ]++;
-        }
-      }
+    for ( iNode = 0; iNode < nbNodes; iNode++ )
+    {
+      midlNod[ iNode ] = isSingleNode[iNode] ? 0 : *itNN[ iNode ]++;
+      nextNod[ iNode ] = *itNN[ iNode ]++;
     }
+
     SMDS_MeshElement* aNewElem = 0;
-    if(!elem->IsPoly()) {
-      switch ( nbNodes ) {
-      case 0:
-        return;
-      case 1: { // NODE
+    /*if(!elem->IsPoly())*/ {
+      switch ( baseType ) {
+      case SMDSEntity_0D:
+      case SMDSEntity_Node: { // sweep NODE
         if ( nbSame == 0 ) {
-          if(issimple[0])
+          if ( isSingleNode[0] )
             aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
           else
             aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ], midlNod[ 0 ] );
         }
+        else
+          return;
         break;
       }
-      case 2: { // EDGE
-        if ( nbSame == 0 )
-          aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
-                                    nextNod[ 1 ], nextNod[ 0 ] );
-        else
-          aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
-                                    nextNod[ iNotSameNode ] );
+      case SMDSEntity_Edge: { // sweep EDGE
+        if ( nbDouble == 0 )
+        {
+          if ( nbSame == 0 ) // ---> quadrangle
+            aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
+                                      nextNod[ 1 ], nextNod[ 0 ] );
+          else               // ---> triangle
+            aNewElem = aMesh->AddFace(prevNod[ 0 ], prevNod[ 1 ],
+                                      nextNod[ iNotSameNode ] );
+        }
+        else                 // ---> polygon
+        {
+          vector<const SMDS_MeshNode*> poly_nodes;
+          poly_nodes.push_back( prevNod[0] );
+          poly_nodes.push_back( prevNod[1] );
+          if ( prevNod[1] != nextNod[1] )
+          {
+            if ( midlNod[1]) poly_nodes.push_back( midlNod[1]);
+            poly_nodes.push_back( nextNod[1] );
+          }
+          if ( prevNod[0] != nextNod[0] )
+          {
+            poly_nodes.push_back( nextNod[0] );
+            if ( midlNod[0]) poly_nodes.push_back( midlNod[0]);
+          }
+          switch ( poly_nodes.size() ) {
+          case 3:
+            aNewElem = aMesh->AddFace( poly_nodes[ 0 ], poly_nodes[ 1 ], poly_nodes[ 2 ]);
+            break;
+          case 4:
+            aNewElem = aMesh->AddFace( poly_nodes[ 0 ], poly_nodes[ 1 ],
+                                       poly_nodes[ 2 ], poly_nodes[ 3 ]);
+            break;
+          default:
+            aNewElem = aMesh->AddPolygonalFace (poly_nodes);
+          }
+        }
         break;
       }
-
-      case 3: { // TRIANGLE or quadratic edge
-        if(elem->GetType() == SMDSAbs_Face) { // TRIANGLE
-
-          if ( nbSame == 0 )       // --- pentahedron
-            aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
-                                         nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
-
-          else if ( nbSame == 1 )  // --- pyramid
-            aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
-                                         nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
+      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[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
+          else // 2 same nodes:       ---> tetrahedron
+            aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ],
                                          nextNod[ iNotSameNode ]);
+          break;
         }
-        else { // quadratic edge
-          if(nbSame==0) {     // quadratic quadrangle
-            aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], nextNod[1], prevNod[1],
-                                      midlNod[0], nextNod[2], midlNod[1], prevNod[2]);
-          }
-          else if(nbSame==1) { // quadratic triangle
-            if(sames[0]==2) {
-              return; // medium node on axis
+      case SMDSEntity_Quad_Edge: // sweep quadratic EDGE --->
+        {
+          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 if(sames[0]==0) {
-              aNewElem = aMesh->AddFace(prevNod[0], nextNod[1], prevNod[1],
-                                        nextNod[2], midlNod[1], prevNod[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], nextNod[1], prevNod[1],
+                                          nextNod[2], midlNod[1], prevNod[2]);
+              else // sames[0]==1
+                aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
+                                          midlNod[0], nextNod[2], prevNod[2]);
             }
-            else { // sames[0]==1
-              aNewElem = aMesh->AddFace(prevNod[0], nextNod[0], prevNod[1],
-                                        midlNod[0], nextNod[2], prevNod[2]);
+          }
+          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 {
+          else
             return;
-          }
+          break;
         }
-        break;
-      }
-      case 4: { // QUADRANGLE
+      case SMDSEntity_Quadrangle: { // sweep QUADRANGLE --->
+        if ( nbDouble > 0 ) break;
 
-        if ( nbSame == 0 )       // --- hexahedron
-          aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
-                                       nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);
+        if ( nbSame == 0 )       // ---> hexahedron
+          aNewElem = aMesh->AddVolume (prevNod[ 0 ], prevNod[ 1 ], prevNod[ 2 ], prevNod[ 3 ],
+                                       nextNod[ 0 ], nextNod[ 1 ], nextNod[ 2 ], nextNod[ 3 ]);
 
-        else if ( nbSame == 1 ) { // --- pyramid + pentahedron
-          aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
-                                       nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
+        else if ( nbSame == 1 ) { // ---> pyramid + pentahedron
+          aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iAfterSame ],
+                                       nextNod[ iAfterSame ],  nextNod[ iBeforeSame ],
                                        nextNod[ iSameNode ]);
           newElems.push_back( aNewElem );
-          aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ], prevNod[ iOpposSame ],
-                                       prevNod[ iBeforeSame ],  nextNod[ iAfterSame ],
+          aNewElem = aMesh->AddVolume (prevNod[ iAfterSame ],  prevNod[ iOpposSame ],
+                                       prevNod[ iBeforeSame ], nextNod[ iAfterSame ],
                                        nextNod[ iOpposSame ],  nextNod[ iBeforeSame ] );
         }
-        else if ( nbSame == 2 ) { // pentahedron
+        else if ( nbSame == 2 ) { // ---> pentahedron
           if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] )
             // iBeforeSame is same too
             aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ], prevNod[ iOpposSame ],
-                                         nextNod[ iOpposSame ], prevNod[ iSameNode ],
+                                         nextNod[ iOpposSame ],  prevNod[ iSameNode ],
                                          prevNod[ iAfterSame ],  nextNod[ iAfterSame ]);
           else
             // iAfterSame is same too
-            aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
+            aNewElem = aMesh->AddVolume (prevNod[ iSameNode ],   prevNod[ iBeforeSame ],
                                          nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
                                          prevNod[ iOpposSame ],  nextNod[ iOpposSame ]);
         }
         break;
       }
-      case 6: { // quadratic triangle
-        // create pentahedron with 15 nodes
+      case SMDSEntity_Quad_Triangle: { // sweep Quadratic TRIANGLE --->
+        if ( nbDouble+nbSame != 3 ) break;
         if(nbSame==0) {
-          if(i0>0) { // reversed case
-            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[2], prevNod[1],
-                                         nextNod[0], nextNod[2], nextNod[1],
-                                         prevNod[5], prevNod[4], prevNod[3],
-                                         nextNod[5], nextNod[4], nextNod[3],
-                                         midlNod[0], midlNod[2], midlNod[1]);
-          }
-          else { // not reversed case
-            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
-                                         nextNod[0], nextNod[1], nextNod[2],
-                                         prevNod[3], prevNod[4], prevNod[5],
-                                         nextNod[3], nextNod[4], nextNod[5],
-                                         midlNod[0], midlNod[1], midlNod[2]);
-          }
+          // --->  pentahedron with 15 nodes
+          aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
+                                       nextNod[0], nextNod[1], nextNod[2],
+                                       prevNod[3], prevNod[4], prevNod[5],
+                                       nextNod[3], nextNod[4], nextNod[5],
+                                       midlNod[0], midlNod[1], midlNod[2]);
         }
         else if(nbSame==1) {
-          // 2d order pyramid of 13 nodes
-          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
-          //                                 int n12,int n23,int n34,int n41,
-          //                                 int n15,int n25,int n35,int n45, int ID);
-          int n5 = iSameNode;
-          int n1,n4,n41,n15,n45;
-          if(i0>0) { // reversed case
-            n1 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
-            n4 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
-            n41 = n1 + 3;
-            n15 = n5 + 3;
-            n45 = n4 + 3;
-          }
-          else {
-            n1 = ( n5 == 0 ? nbBaseNodes - 1 : n5 - 1 );
-            n4 = ( n5 + 1 == nbBaseNodes ? 0 : n5 + 1 );
-            n41 = n4 + 3;
-            n15 = n1 + 3;
-            n45 = n5 + 3;
-          }
-          aNewElem = aMesh->AddVolume(prevNod[n1], nextNod[n1],
-                                      nextNod[n4], prevNod[n4], prevNod[n5],
-                                      midlNod[n1], nextNod[n41],
-                                      midlNod[n4], prevNod[n41],
-                                      prevNod[n15], nextNod[n15],
-                                      nextNod[n45], prevNod[n45]);
+          // --->  2d order pyramid of 13 nodes
+          int apex = iSameNode;
+          int i0 = ( apex + 1 ) % nbCorners;
+          int i1 = ( apex - 1 + nbCorners ) % nbCorners;
+          int i0a = apex + 3;
+          int i1a = i1 + 3;
+          int i01 = i0 + 3;
+          aNewElem = aMesh->AddVolume(prevNod[i1], prevNod[i0],
+                                      nextNod[i0], nextNod[i1], prevNod[apex],
+                                      prevNod[i01], midlNod[i0],
+                                      nextNod[i01], midlNod[i1],
+                                      prevNod[i1a], prevNod[i0a],
+                                      nextNod[i0a], nextNod[i1a]);
         }
         else if(nbSame==2) {
-          // 2d order tetrahedron of 10 nodes
-          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4,
-          //                                 int n12,int n23,int n31,
-          //                                 int n14,int n24,int n34, int ID);
+          // --->  2d order tetrahedron of 10 nodes
           int n1 = iNotSameNode;
-          int n2,n3,n12,n23,n31;
-          if(i0>0) { // reversed case
-            n2 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
-            n3 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
-            n12 = n2 + 3;
-            n23 = n3 + 3;
-            n31 = n1 + 3;
-          }
-          else {
-            n2 = ( n1 + 1 == nbBaseNodes ? 0 : n1 + 1 );
-            n3 = ( n1 == 0 ? nbBaseNodes - 1 : n1 - 1 );
-            n12 = n1 + 3;
-            n23 = n2 + 3;
-            n31 = n3 + 3;
-          }
+          int n2 = ( n1 + 1             ) % nbCorners;
+          int n3 = ( n1 + nbCorners - 1 ) % nbCorners;
+          int n12 = n1 + 3;
+          int n23 = n2 + 3;
+          int n31 = n3 + 3;
           aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], prevNod[n3], nextNod[n1],
                                        prevNod[n12], prevNod[n23], prevNod[n31],
                                        midlNod[n1], nextNod[n12], nextNod[n31]);
         }
         break;
       }
-      case 8: { // quadratic quadrangle
-        if(nbSame==0) {
-          // create hexahedron with 20 nodes
-          if(i0>0) { // reversed case
-            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[3], prevNod[2], prevNod[1],
-                                         nextNod[0], nextNod[3], nextNod[2], nextNod[1],
-                                         prevNod[7], prevNod[6], prevNod[5], prevNod[4],
-                                         nextNod[7], nextNod[6], nextNod[5], nextNod[4],
-                                         midlNod[0], midlNod[3], midlNod[2], midlNod[1]);
-          }
-          else { // not reversed case
-            aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
-                                         nextNod[0], nextNod[1], nextNod[2], nextNod[3],
-                                         prevNod[4], prevNod[5], prevNod[6], prevNod[7],
-                                         nextNod[4], nextNod[5], nextNod[6], nextNod[7],
-                                         midlNod[0], midlNod[1], midlNod[2], midlNod[3]);
-          }
+      case SMDSEntity_Quad_Quadrangle: { // sweep Quadratic QUADRANGLE --->
+        if( nbSame == 0 ) {
+          if ( nbDouble != 4 ) break;
+          // --->  hexahedron with 20 nodes
+          aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
+                                       nextNod[0], nextNod[1], nextNod[2], nextNod[3],
+                                       prevNod[4], prevNod[5], prevNod[6], prevNod[7],
+                                       nextNod[4], nextNod[5], nextNod[6], nextNod[7],
+                                       midlNod[0], midlNod[1], midlNod[2], midlNod[3]);
         }
-        else if(nbSame==1) { 
-          // --- pyramid + pentahedron - can not be created since it is needed 
-          // additional middle node ot the center of face
+        else if(nbSame==1) {
+          // ---> pyramid + pentahedron - can not be created since it is needed 
+          // additional middle node at the center of face
           INFOS( " Sweep for face " << elem->GetID() << " can not be created" );
           return;
         }
-        else if(nbSame==2) {
-          // 2d order Pentahedron with 15 nodes
-          //SMDS_MeshVolume* AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int n6,
-          //                                 int n12,int n23,int n31,int n45,int n56,int n64,
-          //                                 int n14,int n25,int n36, int ID);
+        else if( nbSame == 2 ) {
+          if ( nbDouble != 2 ) break;
+          // --->  2d order Pentahedron with 15 nodes
           int n1,n2,n4,n5;
           if ( prevNod[ iBeforeSame ] == nextNod[ iBeforeSame ] ) {
             // iBeforeSame is same too
@@ -3736,19 +3784,10 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
             n4 = iAfterSame;
             n5 = iOpposSame;
           }
-          int n12,n45,n14,n25;
-          if(i0>0) { //reversed case
-            n12 = n1 + 4;
-            n45 = n5 + 4;
-            n14 = n4 + 4;
-            n25 = n2 + 4;
-          }
-          else {
-            n12 = n2 + 4;
-            n45 = n4 + 4;
-            n14 = n1 + 4;
-            n25 = n5 + 4;
-          }
+          int n12 = n2 + 4;
+          int n45 = n4 + 4;
+          int n14 = n1 + 4;
+          int n25 = n5 + 4;
           aNewElem = aMesh->AddVolume (prevNod[n1], prevNod[n2], nextNod[n2],
                                        prevNod[n4], prevNod[n5], nextNod[n5],
                                        prevNod[n12], midlNod[n2], nextNod[n12],
@@ -3757,57 +3796,92 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
         }
         break;
       }
-      default: {
-        // realized for extrusion only
-        //vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
-        //vector<int> quantities (nbNodes + 2);
-
-        //quantities[0] = nbNodes; // bottom of prism
-        //for (int inode = 0; inode < nbNodes; inode++) {
-        //  polyedre_nodes[inode] = prevNod[inode];
-        //}
-
-        //quantities[1] = nbNodes; // top of prism
-        //for (int inode = 0; inode < nbNodes; inode++) {
-        //  polyedre_nodes[nbNodes + inode] = nextNod[inode];
-        //}
-
-        //for (int iface = 0; iface < nbNodes; iface++) {
-        //  quantities[iface + 2] = 4;
-        //  int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
-        //  polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
-        //  polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
-        //  polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
-        //  polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
-        //}
-        //aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
+      case SMDSEntity_BiQuad_Quadrangle: { // sweep BiQuadratic QUADRANGLE --->
+
+        if( nbSame == 0 && nbDouble == 9 ) {
+          // --->  tri-quadratic hexahedron with 27 nodes
+          aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2], prevNod[3],
+                                       nextNod[0], nextNod[1], nextNod[2], nextNod[3],
+                                       prevNod[4], prevNod[5], prevNod[6], prevNod[7],
+                                       nextNod[4], nextNod[5], nextNod[6], nextNod[7],
+                                       midlNod[0], midlNod[1], midlNod[2], midlNod[3],
+                                       prevNod[8], // bottom center
+                                       midlNod[4], midlNod[5], midlNod[6], midlNod[7],
+                                       nextNod[8], // top center
+                                       midlNod[8]);// elem center
+        }
+        else
+        {
+          return;
+        }
         break;
       }
+      case SMDSEntity_Polygon: { // sweep POLYGON
+
+        if ( nbNodes == 6 && nbSame == 0 && nbDouble == 0 ) {
+          // --->  hexagonal prism
+          aNewElem = aMesh->AddVolume (prevNod[0], prevNod[1], prevNod[2],
+                                       prevNod[3], prevNod[4], prevNod[5],
+                                       nextNod[0], nextNod[1], nextNod[2],
+                                       nextNod[3], nextNod[4], nextNod[5]);
+        }
+        break;
+      }
+      default:
+        break;
       }
     }
 
-    if(!aNewElem) {
-      // realized for extrusion only
+    if ( !aNewElem && elem->GetType() == SMDSAbs_Face ) // try to create a polyherdal prism
+    {
+      if ( baseType != SMDSEntity_Polygon )
+      {
+        const std::vector<int>& ind = SMDS_MeshCell::interlacedSmdsOrder(baseType);
+        SMDS_MeshCell::applyInterlace( ind, prevNod );
+        SMDS_MeshCell::applyInterlace( ind, nextNod );
+        SMDS_MeshCell::applyInterlace( ind, midlNod );
+        SMDS_MeshCell::applyInterlace( ind, itNN );
+        SMDS_MeshCell::applyInterlace( ind, isSingleNode );
+        baseType = SMDSEntity_Polygon; // WARNING: change baseType !!!!
+      }
       vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
       vector<int> quantities (nbNodes + 2);
-
-      quantities[0] = nbNodes; // bottom of prism
-      for (int inode = 0; inode < nbNodes; inode++) {
-        polyedre_nodes[inode] = prevNod[inode];
-      }
-
-      quantities[1] = nbNodes; // top of prism
-      for (int inode = 0; inode < nbNodes; inode++) {
-        polyedre_nodes[nbNodes + inode] = nextNod[inode];
-      }
-
-      for (int iface = 0; iface < nbNodes; iface++) {
-        quantities[iface + 2] = 4;
-        int inextface = (iface == nbNodes - 1) ? 0 : iface + 1;
-        polyedre_nodes[2*nbNodes + 4*iface + 0] = prevNod[iface];
-        polyedre_nodes[2*nbNodes + 4*iface + 1] = prevNod[inextface];
-        polyedre_nodes[2*nbNodes + 4*iface + 2] = nextNod[inextface];
-        polyedre_nodes[2*nbNodes + 4*iface + 3] = nextNod[iface];
+      polyedre_nodes.clear();
+      quantities.clear();
+
+      // bottom of prism
+      for (int inode = 0; inode < nbNodes; inode++)
+        polyedre_nodes.push_back( prevNod[inode] );
+      quantities.push_back( nbNodes );
+
+      // top of prism
+      polyedre_nodes.push_back( nextNod[0] );
+      for (int inode = nbNodes; inode-1; --inode )
+        polyedre_nodes.push_back( nextNod[inode-1] );
+      quantities.push_back( nbNodes );
+
+      // side faces
+      for (int iface = 0; iface < nbNodes; iface++)
+      {
+        const int prevNbNodes = polyedre_nodes.size();
+        int inextface = (iface+1) % nbNodes;
+        polyedre_nodes.push_back( prevNod[inextface] );
+        polyedre_nodes.push_back( prevNod[iface] );
+        if ( prevNod[iface] != nextNod[iface] )
+        {
+          if ( midlNod[ iface ]) polyedre_nodes.push_back( midlNod[ iface ]);
+          polyedre_nodes.push_back( nextNod[iface] );
+        }
+        if ( prevNod[inextface] != nextNod[inextface] )
+        {
+          polyedre_nodes.push_back( nextNod[inextface] );
+          if ( midlNod[ inextface ]) polyedre_nodes.push_back( midlNod[ inextface ]);
+        }
+        const int nbFaceNodes = polyedre_nodes.size() - prevNbNodes;
+        if ( nbFaceNodes > 2 )
+          quantities.push_back( nbFaceNodes );
+        else // degenerated face
+          polyedre_nodes.resize( prevNbNodes );
       }
       aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
     }
@@ -3816,7 +3890,6 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement*               elem,
       newElems.push_back( aNewElem );
       myLastCreatedElems.Append(aNewElem);
       srcElements.Append( elem );
-      lastElem = aNewElem;
     }
 
     // set new prev nodes
@@ -3845,14 +3918,14 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
                                   const int                nbSteps,
                                   SMESH_SequenceOfElemPtr& srcElements)
 {
-  MESSAGE("makeWalls");
   ASSERT( newElemsMap.size() == elemNewNodesMap.size() );
   SMESHDS_Mesh* aMesh = GetMeshDS();
 
   // Find nodes belonging to only one initial element - sweep them to get edges.
 
   TNodeOfNodeListMapItr nList = mapNewNodes.begin();
-  for ( ; nList != mapNewNodes.end(); nList++ ) {
+  for ( ; nList != mapNewNodes.end(); nList++ )
+  {
     const SMDS_MeshNode* node =
       static_cast<const SMDS_MeshNode*>( nList->first );
     SMDS_ElemIteratorPtr eIt = node->GetInverseElementIterator();
@@ -3867,11 +3940,10 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         nbInitElems = 0;
         highType = type;
       }
-      if ( elemSet.find(el) != elemSet.end() )
-        nbInitElems++;
+      nbInitElems += elemSet.count(el);
     }
     if ( nbInitElems < 2 ) {
-      bool NotCreateEdge = el && el->IsQuadratic() && el->IsMediumNode(node);
+      bool NotCreateEdge = el && el->IsMediumNode(node);
       if(!NotCreateEdge) {
         vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
         list<const SMDS_MeshElement*> newEdges;
@@ -3885,15 +3957,18 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
 
   TElemOfElemListMap::iterator   itElem      = newElemsMap.begin();
   TElemOfVecOfNnlmiMap::iterator itElemNodes = elemNewNodesMap.begin();
-  for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ ) {
+  for ( ; itElem != newElemsMap.end(); itElem++, itElemNodes++ )
+  {
     const SMDS_MeshElement* elem = itElem->first;
     vector<TNodeOfNodeListMapItr>& vecNewNodes = itElemNodes->second;
 
     if(itElem->second.size()==0) continue;
 
+    const bool isQuadratic = elem->IsQuadratic();
+
     if ( elem->GetType() == SMDSAbs_Edge ) {
       // create a ceiling edge
-      if (!elem->IsQuadratic()) {
+      if ( !isQuadratic ) {
         if ( !aMesh->FindEdge( vecNewNodes[ 0 ]->second.back(),
                                vecNewNodes[ 1 ]->second.back())) {
           myLastCreatedElems.Append(aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
@@ -3922,7 +3997,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
 
     set<const SMDS_MeshNode*> aFaceLastNodes;
     int iNode, nbNodes = vecNewNodes.size();
-    if(!elem->IsQuadratic()) {
+    if ( !isQuadratic ) {
       // loop on the face nodes
       for ( iNode = 0; iNode < nbNodes; iNode++ ) {
         aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
@@ -3954,12 +4029,14 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         int iNext = ( iNode + 1 == nbn ) ? 0 : iNode + 1;
         const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
         const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
+        const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first;
         // check if a link is free
-        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
+        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet ) &&
+             ! SMESH_MeshEditor::FindFaceInSet ( n1, n3, elemSet, avoidSet ) &&
+             ! SMESH_MeshEditor::FindFaceInSet ( n3, n2, elemSet, avoidSet ) ) {
           hasFreeLinks = true;
           // make an edge and a ceiling for a new edge
           // find medium node
-          const SMDS_MeshNode* n3 = vecNewNodes[ iNode+nbn ]->first;
           if ( !aMesh->FindEdge( n1, n2, n3 )) {
             myLastCreatedElems.Append(aMesh->AddEdge( n1, n2, n3 )); // free link edge
             srcElements.Append( myLastCreatedElems.Last() );
@@ -3973,7 +4050,7 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
           }
         }
       }
-      for ( iNode = nbn; iNode < 2*nbn; iNode++ ) {
+      for ( iNode = nbn; iNode < nbNodes; iNode++ ) {
         aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
       }
     }
@@ -3991,12 +4068,11 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
       }
       for ( volNb = 0; volNb < nbVolumesByStep; volNb++ ) {
         list<const SMDS_MeshElement*>::iterator v = newVolumes.begin();
-        iVol = 0;
-        while ( iVol++ < volNb ) v++;
+        std::advance( v, volNb );
         // find indices of free faces of a volume and their source edges
         list< int > freeInd;
         list< const SMDS_MeshElement* > srcEdges; // source edges of free faces
-        SMDS_VolumeTool vTool( *v );
+        SMDS_VolumeTool vTool( *v, /*ignoreCentralNodes=*/false );
         int iF, nbF = vTool.NbFaces();
         for ( iF = 0; iF < nbF; iF ++ ) {
           if (vTool.IsFreeFace( iF ) &&
@@ -4031,96 +4107,137 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         // create faces for all steps;
         // if such a face has been already created by sweep of edge,
         // assure that its orientation is OK
-        for ( int iStep = 0; iStep < nbSteps; iStep++ )  {
-          vTool.Set( *v );
+        for ( int iStep = 0; iStep < nbSteps; iStep++ ) {
+          vTool.Set( *v, /*ignoreCentralNodes=*/false );
           vTool.SetExternalNormal();
+          const int nextShift = vTool.IsForward() ? +1 : -1;
           list< int >::iterator ind = freeInd.begin();
           list< const SMDS_MeshElement* >::iterator srcEdge = srcEdges.begin();
           for ( ; ind != freeInd.end(); ++ind, ++srcEdge ) // loop on free faces
           {
             const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
             int nbn = vTool.NbFaceNodes( *ind );
-            switch ( nbn ) {
-            case 3: { ///// triangle
-              const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
-              if ( !f )
-                myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
-              else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
-                {
-                  myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
-                  aMesh->RemoveElement(f);
-                }
-              break;
+            const SMDS_MeshElement * f = 0;
+            if ( nbn == 3 )              ///// triangle
+            {
+              f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]);
+              if ( !f ||
+                   nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
+              {
+                const SMDS_MeshNode* newOrder[3] = { nodes[ 1 - nextShift ],
+                                                     nodes[ 1 ],
+                                                     nodes[ 1 + nextShift ] };
+                if ( f )
+                  aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+                else
+                  myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+                                                            newOrder[ 2 ] ));
+              }
             }
-            case 4: { ///// quadrangle
-              const SMDS_MeshFace * f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
-              if ( !f )
-                myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
-              else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
-                {
-                  myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
-                  aMesh->RemoveElement(f);
-                }
-              break;
+            else if ( nbn == 4 )       ///// quadrangle
+            {
+              f = aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]);
+              if ( !f ||
+                   nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ]) + nextShift ))
+              {
+                const SMDS_MeshNode* newOrder[4] = { nodes[ 0 ], nodes[ 2-nextShift ],
+                                                     nodes[ 2 ], nodes[ 2+nextShift ] };
+                if ( f )
+                  aMesh->ChangeElementNodes( f, &newOrder[0], nbn );
+                else
+                  myLastCreatedElems.Append(aMesh->AddFace( newOrder[ 0 ], newOrder[ 1 ],
+                                                            newOrder[ 2 ], newOrder[ 3 ]));
+              }
             }
-            default:
-              if( (*v)->IsQuadratic() ) {
-                if(nbn==6) { /////// quadratic triangle
-                  const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4],
-                                                             nodes[1], nodes[3], nodes[5] );
-                  if ( !f ) {
-                    myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
-                                                             nodes[1], nodes[3], nodes[5]));
-                  }
-                  else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) {
-                    const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[6];
-                    tmpnodes[0] = nodes[0];
-                    tmpnodes[1] = nodes[2];
-                    tmpnodes[2] = nodes[4];
-                    tmpnodes[3] = nodes[1];
-                    tmpnodes[4] = nodes[3];
-                    tmpnodes[5] = nodes[5];
-                    myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
-                                                             nodes[1], nodes[3], nodes[5]));
-                    aMesh->RemoveElement(f);
-                  }
-                }
-                else {       /////// quadratic quadrangle
-                  const SMDS_MeshFace * f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
-                                                             nodes[1], nodes[3], nodes[5], nodes[7] );
-                  if ( !f ) {
-                    myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
-                                                             nodes[1], nodes[3], nodes[5], nodes[7]));
-                  }
-                  else if ( nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 )) {
-                    const SMDS_MeshNode** tmpnodes = new const SMDS_MeshNode*[8];
-                    tmpnodes[0] = nodes[0];
-                    tmpnodes[1] = nodes[2];
-                    tmpnodes[2] = nodes[4];
-                    tmpnodes[3] = nodes[6];
-                    tmpnodes[4] = nodes[1];
-                    tmpnodes[5] = nodes[3];
-                    tmpnodes[6] = nodes[5];
-                    tmpnodes[7] = nodes[7];
-                    myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
-                                                             nodes[1], nodes[3], nodes[5], nodes[7]));
-                    aMesh->RemoveElement(f);
-                  }
-                }
+            else if ( nbn == 6 && isQuadratic ) /////// quadratic triangle
+            {
+              f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[1], nodes[3], nodes[5] );
+              if ( !f ||
+                   nodes[2] != f->GetNodeWrap( f->GetNodeIndex( nodes[0] ) + 2*nextShift ))
+              {
+                const SMDS_MeshNode* newOrder[6] = { nodes[2 - 2*nextShift],
+                                                     nodes[2],
+                                                     nodes[2 + 2*nextShift],
+                                                     nodes[3 - 2*nextShift],
+                                                     nodes[3],
+                                                     nodes[3 + 2*nextShift]};
+                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 ] ));
               }
-              else { //////// polygon
-                vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
-                const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
-                if ( !f )
-                  myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
-                else if ( nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 1 ))
-                  {
-                  // TODO problem ChangeElementNodes : not the same number of nodes, not the same type
-                  MESSAGE("ChangeElementNodes");
-                  aMesh->ChangeElementNodes( f, nodes, nbn );
-                  }
+            }
+            else if ( nbn == 8 && isQuadratic ) /////// quadratic quadrangle
+            {
+              f = aMesh->FindFace( nodes[0], nodes[2], nodes[4], nodes[6],
+                                   nodes[1], nodes[3], nodes[5], nodes[7] );
+              if ( !f ||
+                   nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift ))
+              {
+                const SMDS_MeshNode* newOrder[8] = { nodes[0],
+                                                     nodes[4 - 2*nextShift],
+                                                     nodes[4],
+                                                     nodes[4 + 2*nextShift],
+                                                     nodes[1],
+                                                     nodes[5 - 2*nextShift],
+                                                     nodes[5],
+                                                     nodes[5 + 2*nextShift] };
+                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 ]));
+              }
+            }
+            else if ( nbn == 9 && isQuadratic ) /////// bi-quadratic quadrangle
+            {
+              f = aMesh->FindElement( vector<const SMDS_MeshNode*>( nodes, nodes+nbn ),
+                                      SMDSAbs_Face, /*noMedium=*/false);
+              if ( !f ||
+                   nodes[ 2 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + 2*nextShift ))
+              {
+                const SMDS_MeshNode* newOrder[9] = { nodes[0],
+                                                     nodes[4 - 2*nextShift],
+                                                     nodes[4],
+                                                     nodes[4 + 2*nextShift],
+                                                     nodes[1],
+                                                     nodes[5 - 2*nextShift],
+                                                     nodes[5],
+                                                     nodes[5 + 2*nextShift],
+                                                     nodes[8] };
+                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 ]));
+              }
+            }
+            else  //////// polygon
+            {
+              vector<const SMDS_MeshNode*> polygon_nodes ( nodes, nodes+nbn );
+              const SMDS_MeshFace * f = aMesh->FindFace( polygon_nodes );
+              if ( !f ||
+                   nodes[ 1 ] != f->GetNodeWrap( f->GetNodeIndex( nodes[ 0 ] ) + nextShift ))
+              {
+                if ( !vTool.IsForward() )
+                  std::reverse( polygon_nodes.begin(), polygon_nodes.end());
+                if ( f )
+                  aMesh->ChangeElementNodes( f, &polygon_nodes[0], nbn );
+                else
+                  AddElement(polygon_nodes, SMDSAbs_Face, polygon_nodes.size()>4);
               }
             }
+
             while ( srcElements.Length() < myLastCreatedElems.Length() )
               srcElements.Append( *srcEdge );
 
@@ -4129,54 +4246,60 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
           // go to the next volume
           iVol = 0;
           while ( iVol++ < nbVolumesByStep ) v++;
-        }
-      }
+
+        } // loop on steps
+      } // loop on volumes of one step
     } // sweep free links into faces
 
     // Make a ceiling face with a normal external to a volume
 
-    SMDS_VolumeTool lastVol( itElem->second.back() );
+    SMDS_VolumeTool lastVol( itElem->second.back(), /*ignoreCentralNodes=*/false );
 
     int iF = lastVol.GetFaceIndex( aFaceLastNodes );
     if ( iF >= 0 ) {
       lastVol.SetExternalNormal();
       const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
       int nbn = lastVol.NbFaceNodes( iF );
-      switch ( nbn ) {
-      case 3:
+      if ( nbn == 3 ) {
         if (!hasFreeLinks ||
             !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]))
           myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
-        break;
-      case 4:
+      }
+      else if ( nbn == 4 )
+      {
         if (!hasFreeLinks ||
             !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]))
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ));
-        break;
-      default:
-        if(itElem->second.back()->IsQuadratic()) {
-          if(nbn==6) {
-            if (!hasFreeLinks ||
-                !aMesh->FindFace(nodes[0], nodes[2], nodes[4],
-                                 nodes[1], nodes[3], nodes[5]) ) {
-              myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
-                                                       nodes[1], nodes[3], nodes[5]));
-            }
-          }
-          else { // nbn==8
-            if (!hasFreeLinks ||
-                !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
-                                 nodes[1], nodes[3], nodes[5], nodes[7]) )
-              myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
-                                                       nodes[1], nodes[3], nodes[5], nodes[7]));
-          }
-        }
-        else {
-          vector<const SMDS_MeshNode*> polygon_nodes ( nodes, &nodes[nbn] );
-          if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
-            myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
-        }
-      } // switch
+          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ]));
+      }
+      else if ( nbn == 6 && isQuadratic )
+      {
+        if (!hasFreeLinks ||
+            !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[1], nodes[3], nodes[5]) )
+          myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4],
+                                                   nodes[1], nodes[3], nodes[5]));
+      }
+      else if ( nbn == 8 && isQuadratic )
+      {
+        if (!hasFreeLinks ||
+            !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                             nodes[1], nodes[3], nodes[5], nodes[7]) )
+          myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                                                   nodes[1], nodes[3], nodes[5], nodes[7]));
+      }
+      else if ( nbn == 9 && isQuadratic )
+      {
+        if (!hasFreeLinks ||
+            !aMesh->FindElement(vector<const SMDS_MeshNode*>( nodes, nodes+nbn ),
+                                SMDSAbs_Face, /*noMedium=*/false) )
+          myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                                                   nodes[1], nodes[3], nodes[5], nodes[7],
+                                                   nodes[8]));
+      }
+      else {
+        vector<const SMDS_MeshNode*> polygon_nodes ( nodes, nodes + nbn );
+        if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
+          myLastCreatedElems.Append(aMesh->AddPolygonalFace(polygon_nodes));
+      }
 
       while ( srcElements.Length() < myLastCreatedElems.Length() )
         srcElements.Append( myLastCreatedElems.Last() );
@@ -4219,6 +4342,9 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
   TElemOfVecOfNnlmiMap mapElemNewNodes;
   TElemOfElemListMap newElemsMap;
 
+  const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) +
+                                     myMesh->NbFaces(ORDER_QUADRATIC) +
+                                     myMesh->NbVolumes(ORDER_QUADRATIC) );
   // loop on theElems
   TIDSortedElemSet::iterator itElem;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
@@ -4230,7 +4356,8 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
 
     // loop on elem nodes
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() ) {
+    while ( itN->more() )
+    {
       // check if a node has been already sweeped
       const SMDS_MeshNode* node = cast2Node( itN->next() );
 
@@ -4239,33 +4366,43 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
       aXYZ.Coord( coord[0], coord[1], coord[2] );
       bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol );
 
-      TNodeOfNodeListMapItr nIt = mapNewNodes.find( node );
-      if ( nIt == mapNewNodes.end() ) {
-        nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
-        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
+      TNodeOfNodeListMapItr nIt =
+        mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
+      list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
+      if ( listNewNodes.empty() )
+      {
+        // check if we are to create medium nodes between corner ones
+        bool needMediumNodes = false;
+        if ( isQuadraticMesh )
+        {
+          SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+          while (it->more() && !needMediumNodes )
+          {
+            const SMDS_MeshElement* invElem = it->next();
+            if ( invElem != elem && !theElems.count( invElem )) continue;
+            needMediumNodes = ( invElem->IsQuadratic() && !invElem->IsMediumNode(node) );
+            if ( !needMediumNodes && invElem->GetEntityType() == SMDSEntity_BiQuad_Quadrangle )
+              needMediumNodes = true;
+          }
+        }
 
         // make new nodes
-        //gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
-        //double coord[3];
-        //aXYZ.Coord( coord[0], coord[1], coord[2] );
-        //bool isOnAxis = ( aLine.SquareDistance( aXYZ ) <= aSqTol );
         const SMDS_MeshNode * newNode = node;
         for ( int i = 0; i < theNbSteps; i++ ) {
           if ( !isOnAxis ) {
-            if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-              // create two nodes
+            if ( needMediumNodes )  // create a medium node
+            {
               aTrsf2.Transforms( coord[0], coord[1], coord[2] );
-              //aTrsf.Transforms( coord[0], coord[1], coord[2] );
               newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
               myLastCreatedNodes.Append(newNode);
               srcNodes.Append( node );
               listNewNodes.push_back( newNode );
               aTrsf2.Transforms( coord[0], coord[1], coord[2] );
-              //aTrsf.Transforms( coord[0], coord[1], coord[2] );
             }
             else {
               aTrsf.Transforms( coord[0], coord[1], coord[2] );
             }
+            // create a corner node
             newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
             myLastCreatedNodes.Append(newNode);
             srcNodes.Append( node );
@@ -4273,48 +4410,11 @@ SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
           }
           else {
             listNewNodes.push_back( newNode );
-            if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-              listNewNodes.push_back( newNode );
-            }
+            // if ( needMediumNodes )
+            //   listNewNodes.push_back( newNode );
           }
         }
       }
-      /*
-        else {
-        // if current elem is quadratic and current node is not medium
-        // we have to check - may be it is needed to insert additional nodes
-        if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-        list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
-        if(listNewNodes.size()==theNbSteps) {
-        listNewNodes.clear();
-        // make new nodes
-        //gp_XYZ aXYZ( node->X(), node->Y(), node->Z() );
-        //double coord[3];
-        //aXYZ.Coord( coord[0], coord[1], coord[2] );
-        const SMDS_MeshNode * newNode = node;
-        if ( !isOnAxis ) {
-        for(int i = 0; i<theNbSteps; i++) {
-        aTrsf2.Transforms( coord[0], coord[1], coord[2] );
-        newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-        cout<<"    3 AddNode:  "<<newNode;
-        myLastCreatedNodes.Append(newNode);
-        listNewNodes.push_back( newNode );
-        srcNodes.Append( node );
-        aTrsf2.Transforms( coord[0], coord[1], coord[2] );
-        newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-        cout<<"    4 AddNode:  "<<newNode;
-        myLastCreatedNodes.Append(newNode);
-        srcNodes.Append( node );
-        listNewNodes.push_back( newNode );
-        }
-        }
-        else {
-        listNewNodes.push_back( newNode );
-        }
-        }
-        }
-        }
-      */
       newNodesItVec.push_back( nIt );
     }
     // make new elements
@@ -4342,8 +4442,8 @@ const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
                                                   const double tolnode,
                                                   SMESH_SequenceOfNode& aNodes)
 {
-  myLastCreatedElems.Clear();
-  myLastCreatedNodes.Clear();
+  // myLastCreatedElems.Clear();
+  // myLastCreatedNodes.Clear();
 
   gp_Pnt P1(x,y,z);
   SMESHDS_Mesh * aMesh = myMesh->GetMeshDS();
@@ -4371,7 +4471,7 @@ const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
 
   // create new node and return it
   const SMDS_MeshNode* NewNode = aMesh->AddNode(x,y,z);
-  myLastCreatedNodes.Append(NewNode);
+  //myLastCreatedNodes.Append(NewNode);
   return NewNode;
 }
 
@@ -4416,7 +4516,6 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
                                   const int           theFlags,
                                   const double        theTolerance)
 {
-  MESSAGE("ExtrusionSweep " << theMakeGroups << " " << theFlags << " " << theTolerance);
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
 
@@ -4432,6 +4531,9 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
   TElemOfVecOfNnlmiMap mapElemNewNodes;
   //TElemOfVecOfMapNodesMap mapElemNewNodes;
 
+  const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) +
+                                     myMesh->NbFaces(ORDER_QUADRATIC) +
+                                     myMesh->NbVolumes(ORDER_QUADRATIC) );
   // loop on theElems
   TIDSortedElemSet::iterator itElem;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
@@ -4441,7 +4543,6 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
       continue;
 
     vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
-    //vector<TNodeOfNodeVecMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
     newNodesItVec.reserve( elem->NbNodes() );
 
     // loop on elem nodes
@@ -4450,21 +4551,33 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
     {
       // check if a node has been already sweeped
       const SMDS_MeshNode* node = cast2Node( itN->next() );
-      TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
-      //TNodeOfNodeVecMap::iterator nIt = mapNewNodes.find( node );
-      if ( nIt == mapNewNodes.end() ) {
-        nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
-        //nIt = mapNewNodes.insert( make_pair( node, vector<const SMDS_MeshNode*>() )).first;
-        list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
-        //vector<const SMDS_MeshNode*>& vecNewNodes = nIt->second;
-        //vecNewNodes.reserve(nbsteps);
-
+      TNodeOfNodeListMap::iterator nIt =
+        mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
+      list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
+      if ( listNewNodes.empty() )
+      {
         // make new nodes
+
+        // check if we are to create medium nodes between corner ones
+        bool needMediumNodes = false;
+        if ( isQuadraticMesh )
+        {
+          SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+          while (it->more() && !needMediumNodes )
+          {
+            const SMDS_MeshElement* invElem = it->next();
+            if ( invElem != elem && !theElems.count( invElem )) continue;
+            needMediumNodes = ( invElem->IsQuadratic() && !invElem->IsMediumNode(node) );
+            if ( !needMediumNodes && invElem->GetEntityType() == SMDSEntity_BiQuad_Quadrangle )
+              needMediumNodes = true;
+          }
+        }
+
         double coord[] = { node->X(), node->Y(), node->Z() };
-        //int nbsteps = theParams.mySteps->Length();
-        for ( int i = 0; i < nbsteps; i++ ) {
-          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-            // create additional node
+        for ( int i = 0; i < nbsteps; i++ )
+        {
+          if ( needMediumNodes ) // create a medium node
+          {
             double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1)/2.;
             double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1)/2.;
             double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1)/2.;
@@ -4480,7 +4593,7 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
               listNewNodes.push_back( newNode );
             }
           }
-          //aTrsf.Transforms( coord[0], coord[1], coord[2] );
+          // create a corner node
           coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
           coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
           coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
@@ -4488,55 +4601,12 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
             const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
                                                        theTolerance, theParams.myNodes);
             listNewNodes.push_back( newNode );
-            //vecNewNodes[i]=newNode;
           }
           else {
             const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
             myLastCreatedNodes.Append(newNode);
             srcNodes.Append( node );
             listNewNodes.push_back( newNode );
-            //vecNewNodes[i]=newNode;
-          }
-        }
-      }
-      else {
-        // if current elem is quadratic and current node is not medium
-        // we have to check - may be it is needed to insert additional nodes
-        if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
-          list< const SMDS_MeshNode* > & listNewNodes = nIt->second;
-          if(listNewNodes.size()==nbsteps) {
-            listNewNodes.clear();
-            double coord[] = { node->X(), node->Y(), node->Z() };
-            for ( int i = 0; i < nbsteps; i++ ) {
-              double x = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
-              double y = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
-              double z = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
-              if( theFlags & EXTRUSION_FLAG_SEW ) {
-                const SMDS_MeshNode * newNode = CreateNode(x, y, z,
-                                                           theTolerance, theParams.myNodes);
-                listNewNodes.push_back( newNode );
-              }
-              else {
-                const SMDS_MeshNode * newNode = aMesh->AddNode(x, y, z);
-                myLastCreatedNodes.Append(newNode);
-                srcNodes.Append( node );
-                listNewNodes.push_back( newNode );
-              }
-              coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
-              coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
-              coord[2] = coord[2] + theParams.myDir.Z()*theParams.mySteps->Value(i+1);
-              if( theFlags & EXTRUSION_FLAG_SEW ) {
-                const SMDS_MeshNode * newNode = CreateNode(coord[0], coord[1], coord[2],
-                                                           theTolerance, theParams.myNodes);
-                listNewNodes.push_back( newNode );
-              }
-              else {
-                const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-                myLastCreatedNodes.Append(newNode);
-                srcNodes.Append( node );
-                listNewNodes.push_back( newNode );
-              }
-            }
           }
         }
       }
@@ -4556,52 +4626,6 @@ SMESH_MeshEditor::ExtrusionSweep (TIDSortedElemSet &  theElems,
   return newGroupIDs;
 }
 
-/*
-//=======================================================================
-//class    : SMESH_MeshEditor_PathPoint
-//purpose  : auxiliary class
-//=======================================================================
-class SMESH_MeshEditor_PathPoint {
-public:
-SMESH_MeshEditor_PathPoint() {
-myPnt.SetCoord(99., 99., 99.);
-myTgt.SetCoord(1.,0.,0.);
-myAngle=0.;
-myPrm=0.;
-}
-void SetPnt(const gp_Pnt& aP3D){
-myPnt=aP3D;
-}
-void SetTangent(const gp_Dir& aTgt){
-myTgt=aTgt;
-}
-void SetAngle(const double& aBeta){
-myAngle=aBeta;
-}
-void SetParameter(const double& aPrm){
-myPrm=aPrm;
-}
-const gp_Pnt& Pnt()const{
-return myPnt;
-}
-const gp_Dir& Tangent()const{
-return myTgt;
-}
-double Angle()const{
-return myAngle;
-}
-double Parameter()const{
-return myPrm;
-}
-
-protected:
-gp_Pnt myPnt;
-gp_Dir myTgt;
-double myAngle;
-double myPrm;
-};
-*/
-
 //=======================================================================
 //function : ExtrusionAlongTrack
 //purpose  :
@@ -4658,7 +4682,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
   list<SMESH_MeshEditor_PathPoint> fullList;
 
   const TopoDS_Shape& aS = theTrack->GetSubShape();
-  // Sub shape for the Pattern must be an Edge or Wire
+  // 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
@@ -4682,8 +4706,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
     }
     //Extrusion_Error err =
     MakeEdgePathPoints(aPrms, aTrackEdge, (aN1==theN1), fullList);
-  }
-  else if( aS.ShapeType() == TopAbs_WIRE ) {
+  } else if( aS.ShapeType() == TopAbs_WIRE ) {
     list< SMESH_subMesh* > LSM;
     TopTools_SequenceOfShape Edges;
     SMESH_subMeshIteratorPtr itSM = theTrack->getDependsOnIterator(false,true);
@@ -4696,6 +4719,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
     list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
     int startNid = theN1->GetID();
     TColStd_MapOfInteger UsedNums;
+    
     int NbEdges = Edges.Length();
     int i = 1;
     for(; i<=NbEdges; i++) {
@@ -4829,8 +4853,127 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
   list<SMESH_MeshEditor_PathPoint> fullList;
 
   const TopoDS_Shape& aS = theTrack->GetShapeToMesh();
-  // Sub shape for the Pattern must be an Edge or Wire
-  if( aS.ShapeType() == TopAbs_EDGE ) {
+
+  if( aS == SMESH_Mesh::PseudoShape() ) {
+    //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;
+    bool isClosed = false;
+
+    //check start node
+    if( !theTrack->GetMeshDS()->Contains(theN1) ) {
+      return EXTR_BAD_STARTING_NODE;
+    }
+    
+    conn = nbEdgeConnectivity(theN1);
+    if(conn > 2)
+      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++;
+          isClosed = true;
+          break;
+        }
+
+        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;
+    double x1,x2,y1,y2,z1,z2;
+    list< list<SMESH_MeshEditor_PathPoint> > LLPPs;
+    int startNid = theN1->GetID();
+    for(int i = 1; i < aNodesList.size(); i++) {
+      x1 = aNodesList[i-1]->X();x2 = aNodesList[i]->X();
+      y1 = aNodesList[i-1]->Y();y2 = aNodesList[i]->Y();
+      z1 = aNodesList[i-1]->Z();z2 = aNodesList[i]->Z();
+      TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp_Pnt(x1,y1,z1),gp_Pnt(x2,y2,z2));  
+      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( 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!=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 ( BRep_Tool::Degenerated( aTrackEdge ) )
@@ -4923,9 +5066,6 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
       list<SMESH_MeshEditor_PathPoint> currList = *itLLPP;
       itPP = currList.begin();
       SMESH_MeshEditor_PathPoint PP2 = currList.front();
-      gp_Pnt P1 = PP1.Pnt();
-      //cout<<"    PP1: Pnt("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
-      gp_Pnt P2 = PP2.Pnt();
       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,
@@ -5307,7 +5447,7 @@ void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
  *  \param theCopy - if true, create translated copies of theElems
  *  \param theMakeGroups - if true and theCopy, create translated groups
  *  \param theTargetMesh - mesh to copy translated elements into
- *  \retval SMESH_MeshEditor::PGroupIDs - list of ids of created groups
+ *  \return SMESH_MeshEditor::PGroupIDs - list of ids of created groups
  */
 //================================================================================
 
@@ -5456,25 +5596,9 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
   for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
     theElems.insert( *invElemIt );
 
-  // replicate or reverse elements
-  // TODO revoir ordre reverse vtk
-  enum {
-    REV_TETRA   = 0,  //  = nbNodes - 4
-    REV_PYRAMID = 1,  //  = nbNodes - 4
-    REV_PENTA   = 2,  //  = nbNodes - 4
-    REV_FACE    = 3,
-    REV_HEXA    = 4,  //  = nbNodes - 4
-    FORWARD     = 5
-  };
-  int index[][8] = {
-    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_TETRA
-    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_PYRAMID
-    { 2, 1, 0, 5, 4, 3, 0, 0 },  // REV_PENTA
-    { 2, 1, 0, 3, 0, 0, 0, 0 },  // REV_FACE
-    { 2, 1, 0, 3, 6, 5, 4, 7 },  // REV_HEXA
-    { 0, 1, 2, 3, 4, 5, 6, 7 }   // FORWARD
-  };
+  // Replicate or reverse elements
 
+  std::vector<int> iForw;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
   {
     const SMDS_MeshElement* elem = *itElem;
@@ -5485,7 +5609,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     int elemType = elem->GetType();
 
     if (elem->IsPoly()) {
-      // Polygon or Polyhedral Volume
+
+      // polygon or polyhedral volume
       switch ( elemType ) {
       case SMDSAbs_Face:
         {
@@ -5524,7 +5649,6 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
         break;
       case SMDSAbs_Volume:
         {
-          // ATTENTION: Reversing is not yet done!!!
           const SMDS_VtkVolume* aPolyedre =
             dynamic_cast<const SMDS_VtkVolume*>( elem );
           if (!aPolyedre) {
@@ -5532,7 +5656,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
             continue;
           }
 
-          vector<const SMDS_MeshNode*> poly_nodes;
+          vector<const SMDS_MeshNode*> poly_nodes; poly_nodes.reserve( nbNodes );
           vector<int> quantities;
 
           bool allTransformed = true;
@@ -5547,6 +5671,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
               } else {
                 poly_nodes.push_back((*nodeMapIt).second);
               }
+              if ( needReverse && allTransformed )
+                std::reverse( poly_nodes.end() - nbFaceNodes, poly_nodes.end() );
             }
             quantities.push_back(nbFaceNodes);
           }
@@ -5569,50 +5695,14 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
       default:;
       }
       continue;
-    }
+
+    } // elem->isPoly()
 
     // Regular elements
-    int* i = index[ FORWARD ];
-    if ( needReverse && nbNodes > 2) {// reverse mirrored faces and volumes
-      if ( elemType == SMDSAbs_Face )
-        i = index[ REV_FACE ];
-      else
-        i = index[ nbNodes - 4 ];
-    }
-    if(elem->IsQuadratic()) {
-      static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
-      i = anIds;
-      if(needReverse) {
-        if(nbNodes==3) { // quadratic edge
-          static int anIds[] = {1,0,2};
-          i = anIds;
-        }
-        else if(nbNodes==6) { // quadratic triangle
-          static int anIds[] = {0,2,1,5,4,3};
-          i = anIds;
-        }
-        else if(nbNodes==8) { // quadratic quadrangle
-          static int anIds[] = {0,3,2,1,7,6,5,4};
-          i = anIds;
-        }
-        else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
-          static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
-          i = anIds;
-        }
-        else if(nbNodes==13) { // quadratic pyramid of 13 nodes
-          static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
-          i = anIds;
-        }
-        else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
-          static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
-          i = anIds;
-        }
-        else { // nbNodes==20 - quadratic hexahedron with 20 nodes
-          static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
-          i = anIds;
-        }
-      }
-    }
+
+    while ( iForw.size() < nbNodes ) iForw.push_back( iForw.size() );
+    const std::vector<int>& iRev = SMDS_MeshCell::reverseSmdsOrder( elem->GetEntityType() );
+    const std::vector<int>& i = needReverse ? iRev : iForw;
 
     // find transformed nodes
     vector<const SMDS_MeshNode*> nodes(nbNodes);
@@ -5638,349 +5728,24 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     }
     else if ( theCopy ) {
       if ( AddElement( nodes, elem->GetType(), elem->IsPoly() ))
-        srcElems.Append( elem );
-    }
-    else {
-      // reverse element as it was reversed by transformation
-      if ( nbNodes > 2 )
-        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
-    }
-  }
-
-  PGroupIDs newGroupIDs;
-
-  if ( theMakeGroups && theCopy ||
-       theMakeGroups && theTargetMesh )
-    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
-
-  return newGroupIDs;
-}
-
-
-////=======================================================================
-////function : Scale
-////purpose  :
-////=======================================================================
-//
-//SMESH_MeshEditor::PGroupIDs
-//SMESH_MeshEditor::Scale (TIDSortedElemSet & theElems,
-//                         const gp_Pnt&            thePoint,
-//                         const std::list<double>& theScaleFact,
-//                         const bool         theCopy,
-//                         const bool         theMakeGroups,
-//                         SMESH_Mesh*        theTargetMesh)
-//{
-//  MESSAGE("Scale");
-//  myLastCreatedElems.Clear();
-//  myLastCreatedNodes.Clear();
-//
-//  SMESH_MeshEditor targetMeshEditor( theTargetMesh );
-//  SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
-//  SMESHDS_Mesh* aMesh    = GetMeshDS();
-//
-//  double scaleX=1.0, scaleY=1.0, scaleZ=1.0;
-//  std::list<double>::const_iterator itS = theScaleFact.begin();
-//  scaleX = (*itS);
-//  if(theScaleFact.size()==1) {
-//    scaleY = (*itS);
-//    scaleZ= (*itS);
-//  }
-//  if(theScaleFact.size()==2) {
-//    itS++;
-//    scaleY = (*itS);
-//    scaleZ= (*itS);
-//  }
-//  if(theScaleFact.size()>2) {
-//    itS++;
-//    scaleY = (*itS);
-//    itS++;
-//    scaleZ= (*itS);
-//  }
-//
-//  // map old node to new one
-//  TNodeNodeMap nodeMap;
-//
-//  // elements sharing moved nodes; those of them which have all
-//  // nodes mirrored but are not in theElems are to be reversed
-//  TIDSortedElemSet inverseElemSet;
-//
-//  // source elements for each generated one
-//  SMESH_SequenceOfElemPtr srcElems, srcNodes;
-//
-//  // loop on theElems
-//  TIDSortedElemSet::iterator itElem;
-//  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
-//    const SMDS_MeshElement* elem = *itElem;
-//    if ( !elem )
-//      continue;
-//
-//    // loop on elem nodes
-//    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-//    while ( itN->more() ) {
-//
-//      // check if a node has been already transformed
-//      const SMDS_MeshNode* node = cast2Node( itN->next() );
-//      pair<TNodeNodeMap::iterator,bool> n2n_isnew =
-//        nodeMap.insert( make_pair ( node, node ));
-//      if ( !n2n_isnew.second )
-//        continue;
-//
-//      //double coord[3];
-//      //coord[0] = node->X();
-//      //coord[1] = node->Y();
-//      //coord[2] = node->Z();
-//      //theTrsf.Transforms( coord[0], coord[1], coord[2] );
-//      double dx = (node->X() - thePoint.X()) * scaleX;
-//      double dy = (node->Y() - thePoint.Y()) * scaleY;
-//      double dz = (node->Z() - thePoint.Z()) * scaleZ;
-//      if ( theTargetMesh ) {
-//        //const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
-//        const SMDS_MeshNode * newNode =
-//          aTgtMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
-//        n2n_isnew.first->second = newNode;
-//        myLastCreatedNodes.Append(newNode);
-//        srcNodes.Append( node );
-//      }
-//      else if ( theCopy ) {
-//        //const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
-//        const SMDS_MeshNode * newNode =
-//          aMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
-//        n2n_isnew.first->second = newNode;
-//        myLastCreatedNodes.Append(newNode);
-//        srcNodes.Append( node );
-//      }
-//      else {
-//        //aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
-//        aMesh->MoveNode( node, thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
-//        // node position on shape becomes invalid
-//        const_cast< SMDS_MeshNode* > ( node )->SetPosition
-//          ( SMDS_SpacePosition::originSpacePosition() );
-//      }
-//
-//      // keep inverse elements
-//      //if ( !theCopy && !theTargetMesh && needReverse ) {
-//      //  SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
-//      //  while ( invElemIt->more() ) {
-//      //    const SMDS_MeshElement* iel = invElemIt->next();
-//      //    inverseElemSet.insert( iel );
-//      //  }
-//      //}
-//    }
-//  }
-//
-//  // either create new elements or reverse mirrored ones
-//  //if ( !theCopy && !needReverse && !theTargetMesh )
-//  if ( !theCopy && !theTargetMesh )
-//    return PGroupIDs();
-//
-//  TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
-//  for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
-//    theElems.insert( *invElemIt );
-//
-//  // replicate or reverse elements
-//
-//  enum {
-//    REV_TETRA   = 0,  //  = nbNodes - 4
-//    REV_PYRAMID = 1,  //  = nbNodes - 4
-//    REV_PENTA   = 2,  //  = nbNodes - 4
-//    REV_FACE    = 3,
-//    REV_HEXA    = 4,  //  = nbNodes - 4
-//    FORWARD     = 5
-//  };
-//  int index[][8] = {
-//    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_TETRA
-//    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_PYRAMID
-//    { 2, 1, 0, 5, 4, 3, 0, 0 },  // REV_PENTA
-//    { 2, 1, 0, 3, 0, 0, 0, 0 },  // REV_FACE
-//    { 2, 1, 0, 3, 6, 5, 4, 7 },  // REV_HEXA
-//    { 0, 1, 2, 3, 4, 5, 6, 7 }   // FORWARD
-//  };
-//
-//  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-//  {
-//    const SMDS_MeshElement* elem = *itElem;
-//    if ( !elem || elem->GetType() == SMDSAbs_Node )
-//      continue;
-//
-//    int nbNodes = elem->NbNodes();
-//    int elemType = elem->GetType();
-//
-//    if (elem->IsPoly()) {
-//      // Polygon or Polyhedral Volume
-//      switch ( elemType ) {
-//      case SMDSAbs_Face:
-//        {
-//          vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
-//          int iNode = 0;
-//          SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-//          while (itN->more()) {
-//            const SMDS_MeshNode* node =
-//              static_cast<const SMDS_MeshNode*>(itN->next());
-//            TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
-//            if (nodeMapIt == nodeMap.end())
-//              break; // not all nodes transformed
-//            //if (needReverse) {
-//            //  // reverse mirrored faces and volumes
-//            //  poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
-//            //} else {
-//            poly_nodes[iNode] = (*nodeMapIt).second;
-//            //}
-//            iNode++;
-//          }
-//          if ( iNode != nbNodes )
-//            continue; // not all nodes transformed
-//
-//          if ( theTargetMesh ) {
-//            myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
-//            srcElems.Append( elem );
-//          }
-//          else if ( theCopy ) {
-//            myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
-//            srcElems.Append( elem );
-//          }
-//          else {
-//            aMesh->ChangePolygonNodes(elem, poly_nodes);
-//          }
-//        }
-//        break;
-//      case SMDSAbs_Volume:
-//        {
-//          // ATTENTION: Reversing is not yet done!!!
-//          const SMDS_VtkVolume* aPolyedre =
-//            dynamic_cast<const SMDS_VtkVolume*>( elem );
-//          if (!aPolyedre) {
-//            MESSAGE("Warning: bad volumic element");
-//            continue;
-//          }
-//
-//          vector<const SMDS_MeshNode*> poly_nodes;
-//          vector<int> quantities;
-//
-//          bool allTransformed = true;
-//          int nbFaces = aPolyedre->NbFaces();
-//          for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
-//            int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
-//            for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
-//              const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
-//              TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
-//              if (nodeMapIt == nodeMap.end()) {
-//                allTransformed = false; // not all nodes transformed
-//              } else {
-//                poly_nodes.push_back((*nodeMapIt).second);
-//              }
-//            }
-//            quantities.push_back(nbFaceNodes);
-//          }
-//          if ( !allTransformed )
-//            continue; // not all nodes transformed
-//
-//          if ( theTargetMesh ) {
-//            myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
-//            srcElems.Append( elem );
-//          }
-//          else if ( theCopy ) {
-//            myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
-//            srcElems.Append( elem );
-//          }
-//          else {
-//            aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
-//          }
-//        }
-//        break;
-//      default:;
-//      }
-//      continue;
-//    }
-//
-//    // Regular elements
-//    int* i = index[ FORWARD ];
-//    //if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes
-//    //  if ( elemType == SMDSAbs_Face )
-//    //    i = index[ REV_FACE ];
-//    //  else
-//    //    i = index[ nbNodes - 4 ];
-//
-//    if(elem->IsQuadratic()) {
-//      static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
-//      i = anIds;
-//      //if(needReverse) {
-//      //  if(nbNodes==3) { // quadratic edge
-//      //    static int anIds[] = {1,0,2};
-//      //    i = anIds;
-//      //  }
-//      //  else if(nbNodes==6) { // quadratic triangle
-//      //    static int anIds[] = {0,2,1,5,4,3};
-//      //    i = anIds;
-//      //  }
-//      //  else if(nbNodes==8) { // quadratic quadrangle
-//      //    static int anIds[] = {0,3,2,1,7,6,5,4};
-//      //    i = anIds;
-//      //  }
-//      //  else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
-//      //    static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
-//      //    i = anIds;
-//      //  }
-//      //  else if(nbNodes==13) { // quadratic pyramid of 13 nodes
-//      //    static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
-//      //    i = anIds;
-//      //  }
-//      //  else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
-//      //    static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
-//      //    i = anIds;
-//      //  }
-//      //  else { // nbNodes==20 - quadratic hexahedron with 20 nodes
-//      //    static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
-//      //    i = anIds;
-//      //  }
-//      //}
-//    }
-//
-//    // find transformed nodes
-//    vector<const SMDS_MeshNode*> nodes(nbNodes);
-//    int iNode = 0;
-//    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-//    while ( itN->more() ) {
-//      const SMDS_MeshNode* node =
-//        static_cast<const SMDS_MeshNode*>( itN->next() );
-//      TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
-//      if ( nodeMapIt == nodeMap.end() )
-//        break; // not all nodes transformed
-//      nodes[ i [ iNode++ ]] = (*nodeMapIt).second;
-//    }
-//    if ( iNode != nbNodes )
-//      continue; // not all nodes transformed
-//
-//    if ( theTargetMesh ) {
-//      if ( SMDS_MeshElement* copy =
-//           targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
-//        myLastCreatedElems.Append( copy );
-//        srcElems.Append( elem );
-//      }
-//    }
-//    else if ( theCopy ) {
-//      if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
-//        myLastCreatedElems.Append( copy );
-//        srcElems.Append( elem );
-//      }
-//    }
-//    else {
-//      // reverse element as it was reversed by transformation
-//      if ( nbNodes > 2 )
-//        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
-//    }
-//  }
-//
-//  PGroupIDs newGroupIDs;
-//
-//  if ( theMakeGroups && theCopy ||
-//       theMakeGroups && theTargetMesh ) {
-//    string groupPostfix = "scaled";
-//    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
-//  }
-//
-//  return newGroupIDs;
-//}
+        srcElems.Append( elem );
+    }
+    else {
+      // reverse element as it was reversed by transformation
+      if ( nbNodes > 2 )
+        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
+    }
+
+  } // loop on elements
+
+  PGroupIDs newGroupIDs;
+
+  if ( ( theMakeGroups && theCopy ) ||
+       ( theMakeGroups && theTargetMesh ) )
+    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
 
+  return newGroupIDs;
+}
 
 //=======================================================================
 /*!
@@ -6054,9 +5819,9 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
           if ( resElem != sourceElem )
             resultElems.push_back( resElem );
       // do not generate element groups from node ones
-      if ( sourceElem->GetType() == SMDSAbs_Node &&
-           elems( iElem )->GetType() != SMDSAbs_Node )
-        continue;
+//      if ( sourceElem->GetType() == SMDSAbs_Node &&
+//           elems( iElem )->GetType() != SMDSAbs_Node )
+//        continue;
 
       // add resultElems to groups made by ones the sourceElem belongs to
       list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
@@ -6696,7 +6461,7 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF
             continue;
           gp_Vec dirInF = gp_Vec( fNorm ) ^ n1n2;
           double angle = dirInOF.AngleWithRef( dirInF, n1n2 );
-          if ( angle < 0 ) angle += 2*PI;
+          if ( angle < 0 ) angle += 2. * M_PI;
           angle2Face.insert( make_pair( angle, *face ));
         }
         if ( !angle2Face.empty() )
@@ -7047,7 +6812,7 @@ SMESH_ElementSearcher* SMESH_MeshEditor::GetElementSearcher()
 
 //=======================================================================
 /*!
- * \brief Return SMESH_ElementSearcher
+ * \brief Return SMESH_ElementSearcher acting on a sub-set of elements
  */
 //=======================================================================
 
@@ -7382,12 +7147,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
           }
         }
         // BUG 0020185: end
-        iRepl[ nbRepl++ ] = iCur;
       }
       curNodes[ iCur ] = n;
       bool isUnique = nodeSet.insert( n ).second;
       if ( isUnique )
         uniqueNodes[ iUnique++ ] = n;
+      else
+        iRepl[ nbRepl++ ] = iCur;
       iCur++;
     }
 
@@ -7499,7 +7265,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
         }
 
         continue;
-      }
+      } // poly element
 
       // Regular elements
       // TODO not all the possible cases are solved. Find something more generic?
@@ -7672,8 +7438,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
         isOk = false;
         SMDS_VolumeTool hexa (elem);
         hexa.SetExternalNormal();
-        if ( nbUniqueNodes == 4 && nbRepl == 6 ) {
-          //////////////////////// ---> tetrahedron
+        if ( nbUniqueNodes == 4 && nbRepl == 4 ) {
+          //////////////////////// HEX ---> 1 tetrahedron
           for ( int iFace = 0; iFace < 6; iFace++ ) {
             const int *ind = hexa.GetFaceNodesIndices( iFace ); // indices of face nodes
             if (curNodes[ind[ 0 ]] == curNodes[ind[ 1 ]] &&
@@ -7683,12 +7449,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
               int iOppFace = hexa.GetOppFaceIndex( iFace );
               ind = hexa.GetFaceNodesIndices( iOppFace );
               int nbStick = 0;
-              iUnique = 2; // reverse a tetrahedron bottom
               for ( iCur = 0; iCur < 4 && nbStick < 2; iCur++ ) {
                 if ( curNodes[ind[ iCur ]] == curNodes[ind[ iCur + 1 ]] )
                   nbStick++;
-                else if ( iUnique >= 0 )
-                  uniqueNodes[ iUnique-- ] = curNodes[ind[ iCur ]];
               }
               if ( nbStick == 1 ) {
                 // ... and the opposite one - into a triangle.
@@ -7701,6 +7464,45 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
             }
           }
         }
+        else if ( nbUniqueNodes == 6 && nbRepl == 2 ) {
+          //////////////////////// HEX ---> 1 prism
+          int nbTria = 0, iTria[3];
+          const int *ind; // indices of face nodes
+          // look for triangular faces
+          for ( int iFace = 0; iFace < 6 && nbTria < 3; iFace++ ) {
+            ind = hexa.GetFaceNodesIndices( iFace );
+            TIDSortedNodeSet faceNodes;
+            for ( iCur = 0; iCur < 4; iCur++ )
+              faceNodes.insert( curNodes[ind[iCur]] );
+            if ( faceNodes.size() == 3 )
+              iTria[ nbTria++ ] = iFace;
+          }
+          // check if triangles are opposite
+          if ( nbTria == 2 && iTria[0] == hexa.GetOppFaceIndex( iTria[1] ))
+          {
+            isOk = true;
+            // set nodes of the bottom triangle
+            ind = hexa.GetFaceNodesIndices( iTria[ 0 ]);
+            vector<int> indB;
+            for ( iCur = 0; iCur < 4; iCur++ )
+              if ( ind[iCur] != iRepl[0] && ind[iCur] != iRepl[1])
+                indB.push_back( ind[iCur] );
+            if ( !hexa.IsForward() )
+              std::swap( indB[0], indB[2] );
+            for ( iCur = 0; iCur < 3; iCur++ )
+              uniqueNodes[ iCur ] = curNodes[indB[iCur]];
+            // set nodes of the top triangle
+            const int *indT = hexa.GetFaceNodesIndices( iTria[ 1 ]);
+            for ( iCur = 0; iCur < 3; ++iCur )
+              for ( int j = 0; j < 4; ++j )
+                if ( hexa.IsLinked( indB[ iCur ], indT[ j ] ))
+                {
+                  uniqueNodes[ iCur + 3 ] = curNodes[ indT[ j ]];
+                  break;
+                }
+          }
+          break;
+        }
         else if (nbUniqueNodes == 5 && nbRepl == 4 ) {
           //////////////////// HEXAHEDRON ---> 2 tetrahedrons
           for ( int iFace = 0; iFace < 6; iFace++ ) {
@@ -7838,6 +7640,10 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
             }
           }
         } // if ( nbUniqueNodes == 6 && nbRepl == 4 )
+        else
+        {
+          MESSAGE("MergeNodes() removes hexahedron "<< elem);
+        }
         break;
       } // HEXAHEDRON
 
@@ -7847,8 +7653,9 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
 
     } // if ( nbNodes != nbUniqueNodes ) // some nodes stick
 
-    if ( isOk ) {
-      if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume) {
+    if ( isOk ) { // the elem remains valid after sticking nodes
+      if (elem->IsPoly() && elem->GetType() == SMDSAbs_Volume)
+      {
         // Change nodes of polyedre
         const SMDS_VtkVolume* aPolyedre =
           dynamic_cast<const SMDS_VtkVolume*>( elem );
@@ -7875,28 +7682,25 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
           aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
         }
       }
-      else {
-        //int elemId = elem->GetID();
-        //MESSAGE("Change regular element or polygon " << elemId);
-        SMDSAbs_ElementType etyp = elem->GetType();
+      else // replace non-polyhedron elements
+      {
+        const SMDSAbs_ElementType etyp = elem->GetType();
+        const int elemId               = elem->GetID();
+        const bool isPoly              = (elem->GetEntityType() == SMDSEntity_Polygon);
         uniqueNodes.resize(nbUniqueNodes);
-        SMDS_MeshElement* newElem = 0;
-        if (elem->GetEntityType() == SMDSEntity_Polygon)
-          newElem = this->AddElement(uniqueNodes, etyp, true);
-        else
-          newElem = this->AddElement(uniqueNodes, etyp, false);
-        if (newElem)
-          {
-            myLastCreatedElems.Append(newElem);
-            if ( aShapeId )
-              aMesh->SetMeshElementOnShape( newElem, aShapeId );
-          }
-        aMesh->RemoveElement(elem);
+
+        SMESHDS_SubMesh * sm = aShapeId > 0 ? aMesh->MeshElements(aShapeId) : 0;
+
+        aMesh->RemoveFreeElement(elem, sm, /*fromGroups=*/false);
+        SMDS_MeshElement* newElem = this->AddElement(uniqueNodes, etyp, isPoly, elemId);
+        if ( sm && newElem )
+          sm->AddElement( newElem );
+        if ( elem != newElem )
+          ReplaceElemInGroups( elem, newElem, aMesh );
       }
     }
     else {
       // Remove invalid regular element or invalid polygon
-      //MESSAGE("Remove invalid " << elem->GetID());
       rmElemIds.push_back( elem->GetID() );
     }
 
@@ -9181,10 +8985,34 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
   }
 }
 
+namespace
+{
+  //================================================================================
+  /*!
+   * \brief Transform any volume into data of SMDSEntity_Polyhedra
+   */
+  //================================================================================
+
+  void volumeToPolyhedron( const SMDS_MeshElement*         elem,
+                           vector<const SMDS_MeshNode *> & nodes,
+                           vector<int> &                   nbNodeInFaces )
+  {
+    nodes.clear();
+    nbNodeInFaces.clear();
+    SMDS_VolumeTool vTool ( elem );
+    for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
+    {
+      const SMDS_MeshNode** fNodes = vTool.GetFaceNodes( iF );
+      nodes.insert( nodes.end(), fNodes, fNodes + vTool.NbFaceNodes( iF ));
+      nbNodeInFaces.push_back( vTool.NbFaceNodes( iF ));
+    }
+  }
+}
+
 //=======================================================================
 /*!
  * \brief Convert elements contained in a submesh to quadratic
- * \retval int - nb of checked elements
+ * \return int - nb of checked elements
  */
 //=======================================================================
 
@@ -9196,6 +9024,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
   if( !theSm ) return nbElem;
 
   vector<int> nbNodeInFaces;
+  vector<const SMDS_MeshNode *> nodes;
   SMDS_ElemIteratorPtr ElemItr = theSm->GetElements();
   while(ElemItr->more())
   {
@@ -9203,14 +9032,19 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     const SMDS_MeshElement* elem = ElemItr->next();
     if( !elem || elem->IsQuadratic() ) continue;
 
-    int id = elem->GetID();
-    int nbNodes = elem->NbNodes();
-    SMDSAbs_ElementType aType = elem->GetType();
-
-    vector<const SMDS_MeshNode *> nodes (elem->begin_nodes(), elem->end_nodes());
-    if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
+    // get elem data needed to re-create it
+    //
+    const int id                        = elem->GetID();
+    const int nbNodes                   = elem->NbNodes();
+    const SMDSAbs_ElementType aType     = elem->GetType();
+    const SMDSAbs_EntityType  aGeomType = elem->GetEntityType();
+    nodes.assign(elem->begin_nodes(), elem->end_nodes());
+    if ( aGeomType == SMDSEntity_Polyhedra )
       nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+    else if ( aGeomType == SMDSEntity_Hexagonal_Prism )
+      volumeToPolyhedron( elem, nodes, nbNodeInFaces );
 
+    // remove a linear element
     GetMeshDS()->RemoveFreeElement(elem, theSm, /*fromGroups=*/false);
 
     const SMDS_MeshElement* NewElem = 0;
@@ -9240,21 +9074,22 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
       }
     case SMDSAbs_Volume :
       {
-        switch(nbNodes)
+        switch( aGeomType )
         {
-        case 4:
+        case SMDSEntity_Tetra:
           NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
           break;
-        case 5:
+        case SMDSEntity_Pyramid:
           NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, theForce3d);
           break;
-        case 6:
+        case SMDSEntity_Penta:
           NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, theForce3d);
           break;
-        case 8:
+        case SMDSEntity_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);
         }
@@ -9267,8 +9102,6 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     if( NewElem )
       theSm->AddElement( NewElem );
   }
-//  if (!GetMeshDS()->isCompacted())
-//    GetMeshDS()->compactMesh();
   return nbElem;
 }
 
@@ -9276,6 +9109,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
 //function : ConvertToQuadratic
 //purpose  :
 //=======================================================================
+
 void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
 {
   SMESHDS_Mesh* meshDS = GetMeshDS();
@@ -9325,19 +9159,19 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
       const SMDS_MeshFace* face = aFaceItr->next();
       if(!face || face->IsQuadratic() ) continue;
 
-      int id = face->GetID();
-      int nbNodes = face->NbNodes();
+      const int id = face->GetID();
+      const SMDSAbs_EntityType type = face->GetEntityType();
       vector<const SMDS_MeshNode *> nodes ( face->begin_nodes(), face->end_nodes());
 
       meshDS->RemoveFreeElement(face, smDS, /*fromGroups=*/false);
 
       SMDS_MeshFace * NewFace = 0;
-      switch(nbNodes)
+      switch( type )
       {
-      case 3:
+      case SMDSEntity_Triangle:
         NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], id, theForce3d);
         break;
-      case 4:
+      case SMDSEntity_Quadrangle:
         NewFace = aHelper.AddFace(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
         break;
       default:
@@ -9352,33 +9186,35 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
       const SMDS_MeshVolume* volume = aVolumeItr->next();
       if(!volume || volume->IsQuadratic() ) continue;
 
-      int id = volume->GetID();
-      int nbNodes = volume->NbNodes();
+      const int id = volume->GetID();
+      const SMDSAbs_EntityType type = volume->GetEntityType();
       vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
-      if ( volume->GetEntityType() == SMDSEntity_Polyhedra )
+      if ( type == SMDSEntity_Polyhedra )
         nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
+      else if ( type == SMDSEntity_Hexagonal_Prism )
+        volumeToPolyhedron( volume, nodes, nbNodeInFaces );
 
       meshDS->RemoveFreeElement(volume, smDS, /*fromGroups=*/false);
 
       SMDS_MeshVolume * NewVolume = 0;
-      switch(nbNodes)
+      switch ( type )
       {
-      case 4:
-        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
-                                      nodes[3], id, theForce3d );
+      case SMDSEntity_Tetra:
+        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d );
+        break;
+      case SMDSEntity_Hexa:
+        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
+                                      nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
         break;
-      case 5:
+      case SMDSEntity_Pyramid:
         NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                       nodes[3], nodes[4], id, theForce3d);
         break;
-      case 6:
+      case SMDSEntity_Penta:
         NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
                                       nodes[3], nodes[4], nodes[5], id, theForce3d);
         break;
-      case 8:
-        NewVolume = aHelper.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:
         NewVolume = aHelper.AddPolyhedralVolume(nodes, nbNodeInFaces, id, theForce3d);
       }
@@ -9386,7 +9222,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
     }
   }
 
-  if ( !theForce3d  && !getenv("NO_FixQuadraticElements"))
+  if ( !theForce3d )
   { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
     aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
     aHelper.FixQuadraticElements();
@@ -9407,7 +9243,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
   if ( theElements.empty() ) return;
 
   // we believe that all theElements are of the same type
-  SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
+  const SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
   
   // get all nodes shared by theElements
   TIDSortedNodeSet allNodes;
@@ -9484,8 +9320,8 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
     if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() )
       continue;
 
-    int id = elem->GetID();
-    SMDSAbs_ElementType type = elem->GetType();
+    const int id                   = elem->GetID();
+    const SMDSAbs_ElementType type = elem->GetType();
     vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());
 
     if ( !smDS || !smDS->Contains( elem ))
@@ -9495,7 +9331,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
     SMDS_MeshElement * newElem = 0;
     switch( nodes.size() )
     {
-    case 4: // cases for most multiple element types go first (for optimization)
+    case 4: // cases for most frequently used element types go first (for optimization)
       if ( type == SMDSAbs_Volume )
         newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
       else
@@ -9536,7 +9372,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
 //=======================================================================
 /*!
  * \brief Convert quadratic elements to linear ones and remove quadratic nodes
- * \retval int - nb of checked elements
+ * \return int - nb of checked elements
  */
 //=======================================================================
 
@@ -9745,20 +9581,20 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   SMESHDS_Mesh* aMesh = GetMeshDS();
   // TODO algoritm not OK with vtkUnstructuredGrid: 2 meshes can't share nodes
   //SMDS_Mesh aTmpFacesMesh; // try to use the same mesh
-  set<const SMDS_MeshElement*> faceSet1, faceSet2;
+  TIDSortedElemSet             faceSet1, faceSet2;
   set<const SMDS_MeshElement*> volSet1,  volSet2;
   set<const SMDS_MeshNode*>    nodeSet1, nodeSet2;
-  set<const SMDS_MeshElement*> * faceSetPtr[] = { &faceSet1, &faceSet2 };
-  set<const SMDS_MeshElement*>  * volSetPtr[] = { &volSet1,  &volSet2  };
+  TIDSortedElemSet             * faceSetPtr[] = { &faceSet1, &faceSet2 };
+  set<const SMDS_MeshElement*>  volSetPtr[] = { &volSet1,  &volSet2  };
   set<const SMDS_MeshNode*>    * nodeSetPtr[] = { &nodeSet1, &nodeSet2 };
-  TIDSortedElemSet * elemSetPtr[] = { &theSide1, &theSide2 };
+  TIDSortedElemSet             * elemSetPtr[] = { &theSide1, &theSide2 };
   int iSide, iFace, iNode;
 
   list<const SMDS_MeshElement* > tempFaceList;
   for ( iSide = 0; iSide < 2; iSide++ ) {
     set<const SMDS_MeshNode*>    * nodeSet = nodeSetPtr[ iSide ];
-    TIDSortedElemSet * elemSet = elemSetPtr[ iSide ];
-    set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
+    TIDSortedElemSet             * elemSet = elemSetPtr[ iSide ];
+    TIDSortedElemSet             * faceSet = faceSetPtr[ iSide ];
     set<const SMDS_MeshElement*> * volSet  = volSetPtr [ iSide ];
     set<const SMDS_MeshElement*>::iterator vIt;
     TIDSortedElemSet::iterator eIt;
@@ -9860,16 +9696,8 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
           bool isNewFace = setOfFaceNodeSet.insert( faceNodeSet ).second;
           if ( isNewFace ) {
             // no such a face is given but it still can exist, check it
-            if ( nbNodes == 3 ) {
-              aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2] );
-            }
-            else if ( nbNodes == 4 ) {
-              aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
-            }
-            else {
-              vector<const SMDS_MeshNode *> poly_nodes ( fNodes, & fNodes[nbNodes]);
-              aFreeFace = aMesh->FindFace(poly_nodes);
-            }
+            vector<const SMDS_MeshNode *> nodes ( fNodes, fNodes + nbNodes);
+            aFreeFace = aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false );
           }
           if ( !aFreeFace ) {
             // create a temporary face
@@ -9886,19 +9714,20 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
               //aFreeFace = aTmpFacesMesh.AddPolygonalFace(poly_nodes);
               aFreeFace = aMesh->AddPolygonalFace(poly_nodes);
             }
+            if ( aFreeFace )
+              tempFaceList.push_back( aFreeFace );
           }
-          if ( aFreeFace ) {
+
+          if ( aFreeFace )
             freeFaceList.push_back( aFreeFace );
-            tempFaceList.push_back( aFreeFace );
-          }
 
         } // loop on faces of a volume
 
-        // choose one of several free faces
-        // --------------------------------------
+        // choose one of several free faces of a volume
+        // --------------------------------------------
         if ( freeFaceList.size() > 1 ) {
           // choose a face having max nb of nodes shared by other elems of a side
-          int maxNbNodes = -1/*, nbExcludedFaces = 0*/;
+          int maxNbNodes = -1;
           list<const SMDS_MeshElement* >::iterator fIt = freeFaceList.begin();
           while ( fIt != freeFaceList.end() ) { // loop on free faces
             int nbSharedNodes = 0;
@@ -9909,18 +9738,20 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
               SMDS_ElemIteratorPtr invElemIt = n->GetInverseElementIterator();
               while ( invElemIt->more() ) {
                 const SMDS_MeshElement* e = invElemIt->next();
-                if ( faceSet->find( e ) != faceSet->end() )
-                  nbSharedNodes++;
-                if ( elemSet->find( e ) != elemSet->end() )
-                  nbSharedNodes++;
+                nbSharedNodes += faceSet->count( e );
+                nbSharedNodes += elemSet->count( e );
               }
             }
-            if ( nbSharedNodes >= maxNbNodes ) {
+            if ( nbSharedNodes > maxNbNodes ) {
               maxNbNodes = nbSharedNodes;
+              freeFaceList.erase( freeFaceList.begin(), fIt++ );
+            }
+            else if ( nbSharedNodes == maxNbNodes ) {
               fIt++;
             }
-            else
+            else {
               freeFaceList.erase( fIt++ ); // here fIt++ occurs before erase
+            }
           }
           if ( freeFaceList.size() > 1 )
           {
@@ -10021,9 +9852,9 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
 
   TNodeNodeMap nReplaceMap; // bind a node to remove to a node to put instead
   if ( theFirstNode1 != theFirstNode2 )
-    nReplaceMap.insert( TNodeNodeMap::value_type( theFirstNode1, theFirstNode2 ));
+    nReplaceMap.insert( make_pair( theFirstNode1, theFirstNode2 ));
   if ( theSecondNode1 != theSecondNode2 )
-    nReplaceMap.insert( TNodeNodeMap::value_type( theSecondNode1, theSecondNode2 ));
+    nReplaceMap.insert( make_pair( theSecondNode1, theSecondNode2 ));
 
   LinkID_Gen aLinkID_Gen( GetMeshDS() );
   set< long > linkIdSet; // links to process
@@ -10036,10 +9867,11 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   // loop on links in linkList; find faces by links and append links
   // of the found faces to linkList
   list< NLink >::iterator linkIt[] = { linkList[0].begin(), linkList[1].begin() } ;
-  for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ ) {
+  for ( ; linkIt[0] != linkList[0].end(); linkIt[0]++, linkIt[1]++ )
+  {
     NLink link[] = { *linkIt[0], *linkIt[1] };
     long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
-    if ( linkIdSet.find( linkID ) == linkIdSet.end() )
+    if ( !linkIdSet.count( linkID ) )
       continue;
 
     // by links, find faces in the face sets,
@@ -10048,125 +9880,42 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
     // ---------------------------------------------------------------
 
     const SMDS_MeshElement* face[] = { 0, 0 };
-    //const SMDS_MeshNode* faceNodes[ 2 ][ 5 ];
-    vector<const SMDS_MeshNode*> fnodes1(9);
-    vector<const SMDS_MeshNode*> fnodes2(9);
-    //const SMDS_MeshNode* notLinkNodes[ 2 ][ 2 ] = {{ 0, 0 },{ 0, 0 }} ;
-    vector<const SMDS_MeshNode*> notLinkNodes1(6);
-    vector<const SMDS_MeshNode*> notLinkNodes2(6);
+    vector<const SMDS_MeshNode*> fnodes[2];
     int iLinkNode[2][2];
+    TIDSortedElemSet avoidSet;
     for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
       const SMDS_MeshNode* n1 = link[iSide].first;
       const SMDS_MeshNode* n2 = link[iSide].second;
-      set<const SMDS_MeshElement*> * faceSet = faceSetPtr[ iSide ];
-      set< const SMDS_MeshElement* > fMap;
-      for ( int i = 0; i < 2; i++ ) { // loop on 2 nodes of a link
-        const SMDS_MeshNode* n = i ? n1 : n2; // a node of a link
-        SMDS_ElemIteratorPtr fIt = n->GetInverseElementIterator(SMDSAbs_Face);
-        while ( fIt->more() ) { // loop on faces sharing a node
-          const SMDS_MeshElement* f = fIt->next();
-          if (faceSet->find( f ) != faceSet->end() && // f is in face set
-              ! fMap.insert( f ).second ) // f encounters twice
-          {
-            if ( face[ iSide ] ) {
-              MESSAGE( "2 faces per link " );
-              aResult = iSide ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES;
-              break;
-            }
-            face[ iSide ] = f;
-            faceSet->erase( f );
-            // get face nodes and find ones of a link
-            iNode = 0;
-            int nbl = -1;
-            if(f->IsPoly()) {
-              if(iSide==0) {
-                fnodes1.resize(f->NbNodes()+1);
-                notLinkNodes1.resize(f->NbNodes()-2);
-              }
-              else {
-                fnodes2.resize(f->NbNodes()+1);
-                notLinkNodes2.resize(f->NbNodes()-2);
-              }
-            }
-            if(!f->IsQuadratic()) {
-              SMDS_ElemIteratorPtr nIt = f->nodesIterator();
-              while ( nIt->more() ) {
-                const SMDS_MeshNode* n =
-                  static_cast<const SMDS_MeshNode*>( nIt->next() );
-                if ( n == n1 ) {
-                  iLinkNode[ iSide ][ 0 ] = iNode;
-                }
-                else if ( n == n2 ) {
-                  iLinkNode[ iSide ][ 1 ] = iNode;
-                }
-                //else if ( notLinkNodes[ iSide ][ 0 ] )
-                //  notLinkNodes[ iSide ][ 1 ] = n;
-                //else
-                //  notLinkNodes[ iSide ][ 0 ] = n;
-                else {
-                  nbl++;
-                  if(iSide==0)
-                    notLinkNodes1[nbl] = n;
-                  //notLinkNodes1.push_back(n);
-                  else
-                    notLinkNodes2[nbl] = n;
-                  //notLinkNodes2.push_back(n);
-                }
-                //faceNodes[ iSide ][ iNode++ ] = n;
-                if(iSide==0) {
-                  fnodes1[iNode++] = n;
-                }
-                else {
-                  fnodes2[iNode++] = n;
-                }
-              }
-            }
-            else { // f->IsQuadratic()
-              const SMDS_VtkFace* F =
-                dynamic_cast<const SMDS_VtkFace*>(f);
-              if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-              // use special nodes iterator
-              SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-              while ( anIter->more() ) {
-                const SMDS_MeshNode* n =
-                  static_cast<const SMDS_MeshNode*>( anIter->next() );
-                if ( n == n1 ) {
-                  iLinkNode[ iSide ][ 0 ] = iNode;
-                }
-                else if ( n == n2 ) {
-                  iLinkNode[ iSide ][ 1 ] = iNode;
-                }
-                else {
-                  nbl++;
-                  if(iSide==0) {
-                    notLinkNodes1[nbl] = n;
-                  }
-                  else {
-                    notLinkNodes2[nbl] = n;
-                  }
-                }
-                if(iSide==0) {
-                  fnodes1[iNode++] = n;
-                }
-                else {
-                  fnodes2[iNode++] = n;
-                }
-              }
-            }
-            //faceNodes[ iSide ][ iNode ] = faceNodes[ iSide ][ 0 ];
-            if(iSide==0) {
-              fnodes1[iNode] = fnodes1[0];
-            }
-            else {
-              fnodes2[iNode] = fnodes1[0];
-            }
-          }
+      //cout << "Side " << iSide << " ";
+      //cout << "L( " << n1->GetID() << ", " << n2->GetID() << " ) " << endl;
+      // find a face by two link nodes
+      face[ iSide ] = FindFaceInSet( n1, n2, *faceSetPtr[ iSide ], avoidSet,
+                                     &iLinkNode[iSide][0], &iLinkNode[iSide][1] );
+      if ( face[ iSide ])
+      {
+        //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() );
+        }
+        fnodes[ iSide ].push_back( fnodes[ iSide ].front());
       }
     }
 
     // check similarity of elements of the sides
-    if (aResult == SEW_OK && ( face[0] && !face[1] ) || ( !face[0] && face[1] )) {
+    if (aResult == SEW_OK && (( face[0] && !face[1] ) || ( !face[0] && face[1] ))) {
       MESSAGE("Correspondent face not found on side " << ( face[0] ? 1 : 0 ));
       if ( nReplaceMap.size() == 2 ) { // faces on input nodes not found
         aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
@@ -10174,86 +9923,60 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
       else {
         aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
       }
-      break; // do not return because it s necessary to remove tmp faces
+      break; // do not return because it's necessary to remove tmp faces
     }
 
     // set nodes to merge
     // -------------------
 
     if ( face[0] && face[1] )  {
-      int nbNodes = face[0]->NbNodes();
+      const int nbNodes = face[0]->NbNodes();
       if ( nbNodes != face[1]->NbNodes() ) {
         MESSAGE("Diff nb of face nodes");
         aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
         break; // do not return because it s necessary to remove tmp faces
       }
-      bool reverse[] = { false, false }; // order of notLinkNodes of quadrangle
-      if ( nbNodes == 3 ) {
-        //nReplaceMap.insert( TNodeNodeMap::value_type
-        //                   ( notLinkNodes[0][0], notLinkNodes[1][0] ));
-        nReplaceMap.insert( TNodeNodeMap::value_type
-                            ( notLinkNodes1[0], notLinkNodes2[0] ));
+      bool reverse[] = { false, false }; // order of nodes in the link
+      for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
+        // analyse link orientation in faces
+        int i1 = iLinkNode[ iSide ][ 0 ];
+        int i2 = iLinkNode[ iSide ][ 1 ];
+        reverse[ iSide ] = Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1;
       }
-      else {
-        for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
-          // analyse link orientation in faces
-          int i1 = iLinkNode[ iSide ][ 0 ];
-          int i2 = iLinkNode[ iSide ][ 1 ];
-          reverse[ iSide ] = Abs( i1 - i2 ) == 1 ? i1 > i2 : i2 > i1;
-          // if notLinkNodes are the first and the last ones, then
-          // their order does not correspond to the link orientation
-          if (( i1 == 1 && i2 == 2 ) ||
-              ( i1 == 2 && i2 == 1 ))
-            reverse[ iSide ] = !reverse[ iSide ];
-        }
-        if ( reverse[0] == reverse[1] ) {
-          //nReplaceMap.insert( TNodeNodeMap::value_type
-          //                   ( notLinkNodes[0][0], notLinkNodes[1][0] ));
-          //nReplaceMap.insert( TNodeNodeMap::value_type
-          //                   ( notLinkNodes[0][1], notLinkNodes[1][1] ));
-          for(int nn=0; nn<nbNodes-2; nn++) {
-            nReplaceMap.insert( TNodeNodeMap::value_type
-                                ( notLinkNodes1[nn], notLinkNodes2[nn] ));
-          }
-        }
-        else {
-          //nReplaceMap.insert( TNodeNodeMap::value_type
-          //                   ( notLinkNodes[0][0], notLinkNodes[1][1] ));
-          //nReplaceMap.insert( TNodeNodeMap::value_type
-          //                   ( notLinkNodes[0][1], notLinkNodes[1][0] ));
-          for(int nn=0; nn<nbNodes-2; nn++) {
-            nReplaceMap.insert( TNodeNodeMap::value_type
-                                ( notLinkNodes1[nn], notLinkNodes2[nbNodes-3-nn] ));
-          }
-        }
+      int di1 = reverse[0] ? -1 : +1, i1 = iLinkNode[0][1] + di1;
+      int di2 = reverse[1] ? -1 : +1, i2 = iLinkNode[1][1] + di2;
+      for ( int i = nbNodes - 2; i > 0; --i, i1 += di1, i2 += di2 )
+      {
+        nReplaceMap.insert  ( make_pair ( fnodes[0][ ( i1 + nbNodes ) % nbNodes ],
+                                          fnodes[1][ ( i2 + nbNodes ) % nbNodes ]));
       }
 
       // add other links of the faces to linkList
       // -----------------------------------------
 
-      //const SMDS_MeshNode** nodes = faceNodes[ 0 ];
       for ( iNode = 0; iNode < nbNodes; iNode++ )  {
-        //linkID = aLinkID_Gen.GetLinkID( nodes[iNode], nodes[iNode+1] );
-        linkID = aLinkID_Gen.GetLinkID( fnodes1[iNode], fnodes1[iNode+1] );
+        linkID = aLinkID_Gen.GetLinkID( fnodes[0][iNode], fnodes[0][iNode+1] );
         pair< set<long>::iterator, bool > iter_isnew = linkIdSet.insert( linkID );
         if ( !iter_isnew.second ) { // already in a set: no need to process
           linkIdSet.erase( iter_isnew.first );
         }
         else // new in set == encountered for the first time: add
         {
-          //const SMDS_MeshNode* n1 = nodes[ iNode ];
-          //const SMDS_MeshNode* n2 = nodes[ iNode + 1];
-          const SMDS_MeshNode* n1 = fnodes1[ iNode ];
-          const SMDS_MeshNode* n2 = fnodes1[ iNode + 1];
+          const SMDS_MeshNode* n1 = fnodes[0][ iNode ];
+          const SMDS_MeshNode* n2 = fnodes[0][ iNode + 1];
           linkList[0].push_back ( NLink( n1, n2 ));
           linkList[1].push_back ( NLink( nReplaceMap[n1], nReplaceMap[n2] ));
         }
       }
     } // 2 faces found
+
+    if ( faceSetPtr[0]->empty() || faceSetPtr[1]->empty() )
+      break;
+
   } // loop on link lists
 
   if ( aResult == SEW_OK &&
-       ( linkIt[0] != linkList[0].end() ||
+       ( //linkIt[0] != linkList[0].end() ||
          !faceSetPtr[0]->empty() || !faceSetPtr[1]->empty() )) {
     MESSAGE( (linkIt[0] != linkList[0].end()) <<" "<< (faceSetPtr[0]->empty()) <<
              " " << (faceSetPtr[1]->empty()));
@@ -10264,13 +9987,13 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
   // 3. Replace nodes in elements of the side 1 and remove replaced nodes
   // ====================================================================
 
-  // delete temporary faces: they are in reverseElements of actual nodes
+  // delete temporary faces
 //  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);
+  list<const SMDS_MeshElement* >::iterator tmpFaceIt = tempFaceList.begin();
+  for (; tmpFaceIt !=tempFaceList.end(); ++tmpFaceIt)
+    aMesh->RemoveElement(*tmpFaceIt);
 
   if ( aResult != SEW_OK)
     return aResult;
@@ -10337,7 +10060,7 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
  * \param theSecondNode1 - a boundary node of set 1 linked with theFirstNode1
  * \param theSecondNode2 - a node of set 2 corresponding to theSecondNode1
  * \param nReplaceMap - output map of corresponding nodes
- * \retval bool  - is a success or not
+ * \return bool  - is a success or not
  */
 //================================================================================
 
@@ -10748,7 +10471,11 @@ namespace {
       _extremum.Perform(aPnt);
       if ( _extremum.IsDone() )
         for ( int iSol = 1; iSol <= _extremum.NbExt() && _state == TopAbs_OUT; ++iSol)
+#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
+          _state = ( _extremum.SquareDistance(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
+#else
           _state = ( _extremum.Value(iSol) <= theTol ? TopAbs_IN : TopAbs_OUT );
+#endif
     }
     TopAbs_State State() const
     {
@@ -10847,6 +10574,7 @@ double SMESH_MeshEditor::OrientedAngle(const gp_Pnt& p0, const gp_Pnt& p1, const
  * The nodes of the internal faces at the boundaries of the groups are doubled.
  * In option, the internal faces are replaced by flat elements.
  * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * The flat elements are stored in groups of volumes.
  * @param theElems - list of groups of volumes, where a group of volume is a set of
  * SMDS_MeshElements sorted by Id.
  * @param createJointElems - if TRUE, create the elements
@@ -10860,7 +10588,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   MESSAGE("----------------------------------------------");
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
-  meshDS->BuildDownWardConnectivity(false);
+  meshDS->BuildDownWardConnectivity(true);
   CHRONO(50);
   SMDS_UnstructuredGrid *grid = meshDS->getGrid();
 
@@ -10888,6 +10616,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       //     and corresponding volume of this domain, for each shared face.
       //     a volume has a face shared by 2 domains if it has a neighbor which is not in is domain.
 
+      //MESSAGE("Domain " << idom);
       const TIDSortedElemSet& domain = theElems[idom];
       TIDSortedElemSet::const_iterator elemItr = domain.begin();
       for (; elemItr != domain.end(); ++elemItr)
@@ -10896,6 +10625,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           if (!anElem)
             continue;
           int vtkId = anElem->getVtkId();
+          //MESSAGE("  vtkId " << vtkId << " smdsId " << anElem->GetID());
           int neighborsVtkIds[NBMAXNEIGHBORS];
           int downIds[NBMAXNEIGHBORS];
           unsigned char downTypes[NBMAXNEIGHBORS];
@@ -10913,6 +10643,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                     {
                       faceDomains[face][idom] = vtkId; // volume associated to face in this domain
                       celldom[vtkId] = idom;
+                      //MESSAGE("       cell with a border " << vtkId << " domain " << idom);
                     }
                 }
             }
@@ -10928,6 +10659,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
 
   for (int idomain = 0; idomain < theElems.size(); idomain++)
     {
+      //MESSAGE("Domain " << idomain);
       const TIDSortedElemSet& domain = theElems[idomain];
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
@@ -10956,11 +10688,18 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                     continue;
                   int vtkType = grid->GetCellType(vtkId);
                   int downId = grid->CellIdToDownId(vtkId);
+                  if (downId < 0)
+                    {
+                      MESSAGE("doubleNodesOnGroupBoundaries: internal algorithm problem");
+                      continue; // not OK at this stage of the algorithm:
+                                //no cells created after BuildDownWardConnectivity
+                    }
                   DownIdType aCell(downId, vtkType);
                   if (celldom.count(vtkId))
                     continue;
                   cellDomains[aCell][idomain] = vtkId;
                   celldom[vtkId] = idomain;
+                  //MESSAGE("       cell " << vtkId << " domain " << idomain);
                 }
             }
         }
@@ -10975,7 +10714,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //     the value is the ordered domain ids. (more than 4 domains not taken into account)
 
   std::map<std::vector<int>, std::vector<int> > edgesMultiDomains; // nodes of edge --> ordered domains
-  std::map<int, std::vector<int> > mutipleNodes; // nodes muti domains with domain order
+  std::map<int, std::vector<int> > mutipleNodes; // nodes multi domains with domain order
+  std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)
 
   for (int idomain = 0; idomain < theElems.size(); idomain++)
     {
@@ -11033,6 +10773,11 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                       nodeDomains[oldId][idom] = newId; // cloned node for other domains
                       //MESSAGE("   newNode " << newId << " oldNode " << oldId << " size=" <<nodeDomains[oldId].size());
                     }
+                  if (nodeDomains[oldId].size() >= 3)
+                    {
+                      //MESSAGE("confirm multiple node " << oldId);
+                      isMultipleDetected =true;
+                    }
                 }
             }
           if (isMultipleDetected) // check if an edge of the face is shared between 3 or more domains
@@ -11040,76 +10785,89 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               //MESSAGE("multiple Nodes detected on a shared face");
               int downId = itface->first.cellId;
               unsigned char cellType = itface->first.cellType;
-              int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
-              const int *downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
-              const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
-              for (int ie =0; ie < nbEdges; ie++)
+              // --- shared edge or shared face ?
+              if ((cellType == VTK_LINE) || (cellType == VTK_QUADRATIC_EDGE)) // shared edge (between two faces)
                 {
                   int nodes[3];
-                  int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
-                  if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
+                  int nbNodes = grid->getDownArray(cellType)->getNodes(downId, nodes);
+                  for (int i=0; i< nbNodes; i=i+nbNodes-1) // i=0 , i=nbNodes-1
+                    if (mutipleNodes.count(nodes[i]))
+                      if (!mutipleNodesToFace.count(nodes[i]))
+                        mutipleNodesToFace[nodes[i]] = mutipleNodes[nodes[i]];
+               }
+              else // shared face (between two volumes)
+                {
+                  int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
+                  const int* downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
+                  const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
+                  for (int ie =0; ie < nbEdges; ie++)
                     {
-                      vector<int> vn0 = mutipleNodes[nodes[0]];
-                      vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
-                      sort( vn0.begin(), vn0.end() );
-                      sort( vn1.begin(), vn1.end() );
-                      if (vn0 == vn1)
+                      int nodes[3];
+                      int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
+                      if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
                         {
-                          //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]);
-                          double *coords = grid->GetPoint(nodes[0]);
-                          gp_Pnt p0(coords[0], coords[1], coords[2]);
-                          coords = grid->GetPoint(nodes[nbNodes - 1]);
-                          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, double> angleDom; // oriented angles between planes defined by edge and volume centers
-                          int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
-                          for (int id=0; id < vn0.size(); id++)
+                          vector<int> vn0 = mutipleNodes[nodes[0]];
+                          vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
+                          sort( vn0.begin(), vn0.end() );
+                          sort( vn1.begin(), vn1.end() );
+                          if (vn0 == vn1)
                             {
-                              int idom = vn0[id];
-                              for (int ivol=0; ivol<nbvol; ivol++)
+                              //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]);
+                              double *coords = grid->GetPoint(nodes[0]);
+                              gp_Pnt p0(coords[0], coords[1], coords[2]);
+                              coords = grid->GetPoint(nodes[nbNodes - 1]);
+                              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, double> angleDom; // oriented angles between planes defined by edge and volume centers
+                              int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
+                              for (int id=0; id < vn0.size(); id++)
                                 {
-                                  int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
-                                  SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
-                                  if (theElems[idom].count(elem))
+                                  int idom = vn0[id];
+                                  for (int ivol=0; ivol<nbvol; ivol++)
                                     {
-                                      SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
-                                      domvol[idom] = svol;
-                                      //MESSAGE("  domain " << idom << " volume " << elem->GetID());
-                                      double values[3];
-                                      vtkIdType npts = 0;
-                                      vtkIdType* pts = 0;
-                                      grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
-                                      SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
-                                      if (id ==0)
-                                        {
-                                          gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
-                                          angleDom[idom] = 0;
-                                        }
-                                      else
+                                      int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
+                                      SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
+                                      if (theElems[idom].count(elem))
                                         {
-                                          gp_Pnt g(values[0], values[1], values[2]);
-                                          angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
-                                          //MESSAGE("  angle=" << angleDom[idom]);
+                                          SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
+                                          domvol[idom] = svol;
+                                          //MESSAGE("  domain " << idom << " volume " << elem->GetID());
+                                          double values[3];
+                                          vtkIdType npts = 0;
+                                          vtkIdType* pts = 0;
+                                          grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
+                                          SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
+                                          if (id ==0)
+                                            {
+                                              gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+                                              angleDom[idom] = 0;
+                                            }
+                                          else
+                                            {
+                                              gp_Pnt g(values[0], values[1], values[2]);
+                                              angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
+                                              //MESSAGE("  angle=" << angleDom[idom]);
+                                            }
+                                          break;
                                         }
-                                      break;
                                     }
                                 }
+                              map<double, int> sortedDom; // sort domains by angle
+                              for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
+                                sortedDom[ia->second] = ia->first;
+                              vector<int> vnodes;
+                              vector<int> vdom;
+                              for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
+                                {
+                                  vdom.push_back(ib->second);
+                                  //MESSAGE("  ordered domain " << ib->second << "  angle " << ib->first);
+                                }
+                              for (int ino = 0; ino < nbNodes; ino++)
+                                vnodes.push_back(nodes[ino]);
+                              edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains
                             }
-                          map<double, int> sortedDom; // sort domains by angle
-                          for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
-                            sortedDom[ia->second] = ia->first;
-                          vector<int> vnodes;
-                          vector<int> vdom;
-                          for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
-                            {
-                              vdom.push_back(ib->second);
-                              //MESSAGE("  ordered domain " << ib->second << "  angle " << ib->first);
-                            }
-                          for (int ino = 0; ino < nbNodes; ino++)
-                            vnodes.push_back(nodes[ino]);
-                          edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains
                         }
                     }
                 }
@@ -11125,11 +10883,12 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //     (domain1 X domain2) = domain1 + MAXINT*domain2
 
   std::map<int, std::map<long,int> > nodeQuadDomains;
+  std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
 
   if (createJointElems)
     {
       itface = faceDomains.begin();
-      for( ; itface != faceDomains.end();++itface )
+      for (; itface != faceDomains.end(); ++itface)
         {
           DownIdType face = itface->first;
           std::set<int> oldNodes;
@@ -11137,21 +10896,62 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           oldNodes.clear();
           grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
 
-          std::map<int,int> domvol = itface->second;
-          std::map<int,int>::iterator itdom = domvol.begin();
+          std::map<int, int> domvol = itface->second;
+          std::map<int, int>::iterator itdom = domvol.begin();
           int dom1 = itdom->first;
           int vtkVolId = itdom->second;
           itdom++;
           int dom2 = itdom->first;
-          grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains, nodeQuadDomains);
+          SMDS_MeshCell *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
+                                                             nodeQuadDomains);
+          stringstream grpname;
+          grpname << "j_";
+          if (dom1 < dom2)
+            grpname << dom1 << "_" << dom2;
+          else
+            grpname << dom2 << "_" << dom1;
+          int idg;
+          string namegrp = grpname.str();
+          if (!mapOfJunctionGroups.count(namegrp))
+            mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
+          SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+          if (sgrp)
+            sgrp->Add(vol->GetID());
         }
     }
 
   // --- create volumes on multiple domain intersection if requested
+  //     iterate on mutipleNodesToFace
   //     iterate on edgesMultiDomains
 
   if (createJointElems)
     {
+      // --- iterate on mutipleNodesToFace
+
+      std::map<int, std::vector<int> >::iterator itn =  mutipleNodesToFace.begin();
+      for (; itn != mutipleNodesToFace.end(); ++itn)
+        {
+          int node = itn->first;
+          vector<int> orderDom = itn->second;
+          vector<vtkIdType> orderedNodes;
+          for (int idom = 0; idom <orderDom.size(); idom++)
+            orderedNodes.push_back( nodeDomains[node][orderDom[idom]] );
+            SMDS_MeshFace* face = this->GetMeshDS()->AddFaceFromVtkIds(orderedNodes);
+
+            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);
+            SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+            if (sgrp)
+              sgrp->Add(face->GetID());
+        }
+
+      // --- iterate on edgesMultiDomains
+
       std::map<std::vector<int>, std::vector<int> >::iterator ite = edgesMultiDomains.begin();
       for (; ite != edgesMultiDomains.end(); ++ite)
         {
@@ -11168,10 +10968,22 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                 else
                   for (int idom = orderDom.size()-1; idom >=0; idom--)
                     orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
-              this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
+              SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
+
+              stringstream grpname;
+              grpname << "mj_";
+              grpname << 0 << "_" << 0;
+              int idg;
+              string namegrp = grpname.str();
+              if (!mapOfJunctionGroups.count(namegrp))
+                mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+              SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+              if (sgrp)
+                sgrp->Add(vol->GetID());
             }
           else
             {
+              MESSAGE("Quadratic multiple joints not implemented");
               // TODO quadratic nodes
             }
         }
@@ -11200,6 +11012,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               int vtkId = l.cells[i];
               int vtkType = grid->GetCellType(vtkId);
               int downId = grid->CellIdToDownId(vtkId);
+              if (downId < 0)
+                continue; // new cells: not to be modified
               DownIdType aCell(downId, vtkType);
               int volParents[1000];
               int nbvol = grid->GetParentVolumes(volParents, vtkId);
@@ -11258,6 +11072,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         }
     }
 
+  meshDS->CleanDownWardConnectivity(); // Mesh has been modified, downward connectivity is no more usable, free memory
   grid->BuildLinks();
 
   CHRONOSTOP(50);
@@ -11265,6 +11080,167 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   return true;
 }
 
+/*!
+ * \brief Double nodes on some external faces and create flat elements.
+ * Flat elements are mainly used by some types of mechanic calculations.
+ *
+ * Each group of the list must be constituted of faces.
+ * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * @param theElems - list of groups of faces, where a group of faces is a set of
+ * SMDS_MeshElements sorted by Id.
+ * @return TRUE if operation has been completed successfully, FALSE otherwise
+ */
+bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSortedElemSet>& theElems)
+{
+  MESSAGE("-------------------------------------------------");
+  MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
+  MESSAGE("-------------------------------------------------");
+
+  SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
+
+  // --- For each group of faces
+  //     duplicate the nodes, create a flat element based on the face
+  //     replace the nodes of the faces by their clones
+
+  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
+  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
+  clonedNodes.clear();
+  intermediateNodes.clear();
+  std::map<std::string, SMESH_Group*> mapOfJunctionGroups;
+  mapOfJunctionGroups.clear();
+
+  for (int idom = 0; idom < theElems.size(); idom++)
+    {
+      const TIDSortedElemSet& domain = theElems[idom];
+      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);
+          if (!aFace)
+            continue;
+          // MESSAGE("aFace=" << aFace->GetID());
+          bool isQuad = aFace->IsQuadratic();
+          vector<const SMDS_MeshNode*> ln0, ln1, ln2, ln3, ln4;
+
+          // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
+
+          SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+          while (nodeIt->more())
+            {
+              const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
+              bool isMedium = isQuad && (aFace->IsMediumNode(node));
+              if (isMedium)
+                ln2.push_back(node);
+              else
+                ln0.push_back(node);
+
+              const SMDS_MeshNode* clone = 0;
+              if (!clonedNodes.count(node))
+                {
+                  clone = meshDS->AddNode(node->X(), node->Y(), node->Z());
+                  clonedNodes[node] = clone;
+                }
+              else
+                clone = clonedNodes[node];
+
+              if (isMedium)
+                ln3.push_back(clone);
+              else
+                ln1.push_back(clone);
+
+              const SMDS_MeshNode* inter = 0;
+              if (isQuad && (!isMedium))
+                {
+                  if (!intermediateNodes.count(node))
+                    {
+                      inter = meshDS->AddNode(node->X(), node->Y(), node->Z());
+                      intermediateNodes[node] = inter;
+                    }
+                  else
+                    inter = intermediateNodes[node];
+                  ln4.push_back(inter);
+                }
+            }
+
+          // --- extrude the face
+
+          vector<const SMDS_MeshNode*> ln;
+          SMDS_MeshVolume* vol = 0;
+          vtkIdType aType = aFace->GetVtkType();
+          switch (aType)
+          {
+            case VTK_TRIANGLE:
+              vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]);
+              // MESSAGE("vol prism " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              break;
+            case VTK_QUAD:
+              vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]);
+              // MESSAGE("vol hexa " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln1[3]);
+              break;
+            case VTK_QUADRATIC_TRIANGLE:
+              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2],
+                                      ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]);
+              // MESSAGE("vol quad prism " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln3[0]);
+              ln.push_back(ln3[1]);
+              ln.push_back(ln3[2]);
+              break;
+            case VTK_QUADRATIC_QUAD:
+//              vol = meshDS->AddVolume(ln0[0], ln0[1], ln0[2], ln0[3], ln1[0], ln1[1], ln1[2], ln1[3],
+//                                      ln2[0], ln2[1], ln2[2], ln2[3], ln3[0], ln3[1], ln3[2], ln3[3],
+//                                      ln4[0], ln4[1], ln4[2], ln4[3]);
+              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3],
+                                      ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3],
+                                      ln4[0], ln4[1], ln4[2], ln4[3]);
+              // MESSAGE("vol quad hexa " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln1[3]);
+              ln.push_back(ln3[0]);
+              ln.push_back(ln3[1]);
+              ln.push_back(ln3[2]);
+              ln.push_back(ln3[3]);
+              break;
+            case VTK_POLYGON:
+              break;
+            default:
+              break;
+          }
+
+          if (vol)
+            {
+              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);
+              SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+              if (sgrp)
+                sgrp->Add(vol->GetID());
+            }
+
+          // --- modify the face
+
+          aFace->ChangeNodes(&ln[0], ln.size());
+        }
+    }
+  return true;
+}
+
 //================================================================================
 /*!
  * \brief Generates skin mesh (containing 2D cells) from 3D mesh
@@ -11285,10 +11261,10 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
   while(vIt->more())
   {
     const SMDS_MeshVolume* volume = vIt->next();
-    SMDS_VolumeTool vTool( volume );
+    SMDS_VolumeTool vTool( volume, /*ignoreCentralNodes=*/false );
     vTool.SetExternalNormal();
-    const bool isPoly = volume->IsPoly();
-    const bool isQuad = volume->IsQuadratic();
+    //const bool isPoly = volume->IsPoly();
+    const int iQuad = volume->IsQuadratic();
     for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
     {
       if (!vTool.IsFreeFace(iface))
@@ -11298,18 +11274,20 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
       int nbFaceNodes = vTool.NbFaceNodes(iface);
       const SMDS_MeshNode** faceNodes = vTool.GetFaceNodes(iface);
       int inode = 0;
-      for ( ; inode < nbFaceNodes; inode += isQuad ? 2 : 1)
+      for ( ; inode < nbFaceNodes; inode += iQuad+1)
         nodes.push_back(faceNodes[inode]);
-      if (isQuad)
+      if (iQuad) { // add medium nodes
         for ( inode = 1; inode < nbFaceNodes; inode += 2)
           nodes.push_back(faceNodes[inode]);
-
+        if ( nbFaceNodes == 9 ) // bi-quadratic quad
+          nodes.push_back(faceNodes[8]);
+      }
       // add new face based on volume nodes
-      if (aMesh->FindFace( nodes ) ) {
+      if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) ) {
         nbExisted++;
         continue; // face already exsist
       }
-      AddElement(nodes, SMDSAbs_Face, isPoly && iface == 1);
+      AddElement(nodes, SMDSAbs_Face, ( !iQuad && nbFaceNodes/(iQuad+1) > 4 ));
       nbCreated++;
     }
   }
@@ -11333,13 +11311,12 @@ namespace
  *  \param group - a group to store created boundary elements in
  *  \param targetMesh - a mesh to store created boundary elements in
  *  \param toCopyElements - if true, the checked elements will be copied into the targetMesh
- *  \param toCopyExistingBondary - if true, not only new but also pre-existing
+ *  \param toCopyExistingBoundary - if true, not only new but also pre-existing
  *                                boundary elements will be copied into the targetMesh
  *  \param toAddExistingBondary - if true, not only new but also pre-existing
  *                                boundary elements will be added into the new group
  *  \param aroundElements - if true, elements will be created on boundary of given
- *                          elements else, on boundary of the whole mesh. This
- *                          option works for 2D elements only.
+ *                          elements else, on boundary of the whole mesh.
  * \return nb of added boundary elements
  */
 //================================================================================
@@ -11349,7 +11326,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
                                        SMESH_Group*            group/*=0*/,
                                        SMESH_Mesh*             targetMesh/*=0*/,
                                        bool                    toCopyElements/*=false*/,
-                                       bool                    toCopyExistingBondary/*=false*/,
+                                       bool                    toCopyExistingBoundary/*=false*/,
                                        bool                    toAddExistingBondary/*= false*/,
                                        bool                    aroundElements/*= false*/)
 {
@@ -11359,11 +11336,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   if ( !elements.empty() && (*elements.begin())->GetType() != elemType )
     throw SALOME_Exception(LOCALIZED("wrong element type"));
 
-  if ( aroundElements && elemType == SMDSAbs_Volume )
-    throw SALOME_Exception(LOCALIZED("wrong element type for aroundElements==true"));
-
   if ( !targetMesh )
-    toCopyElements = toCopyExistingBondary = false;
+    toCopyElements = toCopyExistingBoundary = false;
 
   SMESH_MeshEditor tgtEditor( targetMesh ? targetMesh : myMesh );
   SMESHDS_Mesh* aMesh = GetMeshDS(), *tgtMeshDS = tgtEditor.GetMeshDS();
@@ -11374,6 +11348,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() );
   presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2;
 
+  SMESH_MesherHelper helper( *myMesh );
+  const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE );
   SMDS_VolumeTool vTool;
   TIDSortedElemSet avoidSet;
   const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet;
@@ -11398,14 +11374,16 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     vector<const SMDS_MeshElement*> presentBndElems;
     vector<TConnectivity>           missingBndElems;
     TConnectivity nodes;
-    if ( vTool.Set(elem) ) // elem is a volume ------------------------------------------
+    if ( vTool.Set(elem, /*ignoreCentralNodes=*/true) ) // elem is a volume --------------
     {
       vTool.SetExternalNormal();
+      const SMDS_MeshElement* otherVol = 0;
       for ( int iface = 0, n = vTool.NbFaces(); iface < n; iface++ )
       {
-        if (!vTool.IsFreeFace(iface))
+        if ( !vTool.IsFreeFace(iface, &otherVol) &&
+             ( !aroundElements || elements.count( otherVol )))
           continue;
-        int nbFaceNodes = vTool.NbFaceNodes(iface);
+        const int nbFaceNodes = vTool.NbFaceNodes(iface);
         const SMDS_MeshNode** nn = vTool.GetFaceNodes(iface);
         if ( missType == SMDSAbs_Edge ) // boundary edges
         {
@@ -11415,7 +11393,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
             for ( int j = 0; j < nodes.size(); ++j )
               nodes[j] =nn[i+j];
             if ( const SMDS_MeshElement* edge =
-                 aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/0))
+                 aMesh->FindElement(nodes,SMDSAbs_Edge,/*noMedium=*/false))
               presentBndElems.push_back( edge );
             else
               missingBndElems.push_back( nodes );
@@ -11426,14 +11404,33 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
           nodes.clear();
           for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
             nodes.push_back( nn[inode] );
-          if (iQuad)
+          if (iQuad) // add medium nodes
             for ( inode = 1; inode < nbFaceNodes; inode += 2)
               nodes.push_back( nn[inode] );
+          int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27
+          if ( iCenter > 0 )
+            nodes.push_back( vTool.GetNodes()[ iCenter ] );
 
-          if (const SMDS_MeshFace * f = aMesh->FindFace( nodes ) )
+          if (const SMDS_MeshElement * f = aMesh->FindElement( nodes,
+                                                               SMDSAbs_Face, /*noMedium=*/false ))
             presentBndElems.push_back( f );
           else
             missingBndElems.push_back( nodes );
+
+          if ( targetMesh != myMesh )
+          {
+            // add 1D elements on face boundary to be added to a new mesh
+            const SMDS_MeshElement* edge;
+            for ( inode = 0; inode < nbFaceNodes; inode += 1+iQuad)
+            {
+              if ( iQuad )
+                edge = aMesh->FindEdge( nn[inode], nn[inode+1], nn[inode+2]);
+              else
+                edge = aMesh->FindEdge( nn[inode], nn[inode+1]);
+              if ( edge && avoidSet.insert( edge ).second )
+                presentBndElems.push_back( edge );
+            }
+          }
         }
       }
     }
@@ -11464,7 +11461,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     // ---------------------------------
     if ( targetMesh != myMesh )
       // instead of making a map of nodes in this mesh and targetMesh,
-      // we create nodes with same IDs. We can renumber them later, if needed
+      // we create nodes with same IDs.
       for ( int i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& srcNodes = missingBndElems[i];
@@ -11473,9 +11470,9 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
           nodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
         if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                    missType,
-                                                                   /*noMedium=*/true))
+                                                                   /*noMedium=*/false))
           continue;
-        tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
+        tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
         ++nbAddedBnd;
       }
     else
@@ -11484,23 +11481,52 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
         TConnectivity& nodes = missingBndElems[i];
         if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                    missType,
-                                                                   /*noMedium=*/true))
+                                                                   /*noMedium=*/false))
           continue;
-        tgtEditor.AddElement(nodes, missType, elem->IsPoly() && nodes.size()/(iQuad+1)>4);
+        SMDS_MeshElement* elem = 
+          tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
         ++nbAddedBnd;
+
+        // try to set a new element to a shape
+        if ( myMesh->HasShapeToMesh() )
+        {
+          bool ok = true;
+          set< pair<TopAbs_ShapeEnum, int > > mediumShapes;
+          const int nbN = nodes.size() / (iQuad+1 );
+          for ( inode = 0; inode < nbN && ok; ++inode )
+          {
+            pair<int, TopAbs_ShapeEnum> i_stype =
+              helper.GetMediumPos( nodes[inode], nodes[(inode+1)%nbN]);
+            if (( ok = ( i_stype.first > 0 && i_stype.second >= TopAbs_FACE )))
+              mediumShapes.insert( make_pair ( i_stype.second, i_stype.first ));
+          }
+          if ( ok && mediumShapes.size() > 1 )
+          {
+            set< pair<TopAbs_ShapeEnum, int > >::iterator stype_i = mediumShapes.begin();
+            pair<TopAbs_ShapeEnum, int> stype_i_0 = *stype_i;
+            for ( ++stype_i; stype_i != mediumShapes.end() && ok; ++stype_i )
+            {
+              if (( ok = ( stype_i->first != stype_i_0.first )))
+                ok = helper.IsSubShape( aMesh->IndexToShape( stype_i->second ),
+                                        aMesh->IndexToShape( stype_i_0.second ));
+            }
+          }
+          if ( ok && mediumShapes.begin()->first == missShapeType )
+            aMesh->SetMeshElementOnShape( elem, mediumShapes.begin()->second );
+        }
       }
 
     // ----------------------------------
     // 3. Copy present boundary elements
     // ----------------------------------
-    if ( toCopyExistingBondary )
+    if ( toCopyExistingBoundary )
       for ( int i = 0 ; i < presentBndElems.size(); ++i )
       {
         const SMDS_MeshElement* e = presentBndElems[i];
         TConnectivity nodes( e->NbNodes() );
         for ( inode = 0; inode < nodes.size(); ++inode )
           nodes[inode] = getNodeWithSameID( tgtMeshDS, e->GetNode(inode) );
-        presentEditor->AddElement(nodes, missType, e->IsPoly());
+        presentEditor->AddElement(nodes, e->GetType(), e->IsPoly());
       }
     else // store present elements to add them to a group
       for ( int i = 0 ; i < presentBndElems.size(); ++i )