]> SALOME platform Git repositories - modules/smesh.git/commitdiff
Salome HOME
Changes for working with quadratic elements.
authorskl <skl@opencascade.com>
Mon, 20 Feb 2006 07:50:46 +0000 (07:50 +0000)
committerskl <skl@opencascade.com>
Mon, 20 Feb 2006 07:50:46 +0000 (07:50 +0000)
28 files changed:
src/Controls/SMESH_Controls.cxx
src/OBJECT/SMESH_Object.cxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMDS/SMDS_MeshElement.cxx
src/SMDS/SMDS_MeshElement.hxx
src/SMDS/SMDS_VolumeTool.cxx
src/SMESH/SMESH_2D_Algo.cxx
src/SMESH/SMESH_2D_Algo.hxx
src/SMESH/SMESH_3D_Algo.cxx
src/SMESH/SMESH_3D_Algo.hxx
src/SMESH/SMESH_Algo.hxx
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESHGUI/SMESHGUI_MultiEditDlg.cxx
src/StdMeshers/Makefile.in
src/StdMeshers/StdMeshers_Helper.cxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Helper.hxx [new file with mode: 0644]
src/StdMeshers/StdMeshers_Hexa_3D.cxx
src/StdMeshers/StdMeshers_Hexa_3D.hxx
src/StdMeshers/StdMeshers_MEFISTO_2D.cxx
src/StdMeshers/StdMeshers_MEFISTO_2D.hxx
src/StdMeshers/StdMeshers_Penta_3D.cxx
src/StdMeshers/StdMeshers_Penta_3D.hxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.hxx
src/StdMeshers/StdMeshers_QuadraticMesh.cxx
src/StdMeshers/StdMeshers_Regular_1D.cxx

index 153a0baee897860ada0862eb8e715ec2acef5aae..fdb9bfe629f82b61fecc4d91ce0dc14c27cde83d 100644 (file)
@@ -164,9 +164,9 @@ bool NumericalFunctor::GetPoints(const SMDS_MeshElement* anElem,
 
   // Get nodes of the element
 
-  const SMDS_QuadraticFaceOfNodes* F =
-    static_cast<const SMDS_QuadraticFaceOfNodes*>(anElem);
-  if(F) {
+  if(anElem->IsQuadratic()) {
+    const SMDS_QuadraticFaceOfNodes* F =
+      static_cast<const SMDS_QuadraticFaceOfNodes*>(anElem);
     // use special nodes iterator
     SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
     if ( anIter != 0 ) {
index db595bc46159c231af4b82bb3e6c329dd82de356..e49f046814a231c277787a5bf59d944243a5db2d 100644 (file)
@@ -616,15 +616,12 @@ static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
       else if ( theNbNodes == 6 )   return VTK_WEDGE;
       else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
       else if ( theNbNodes == 10 )  {
-        cout<<"QUADRATIC_TETRA"<<endl;
         return VTK_QUADRATIC_TETRA;
       }
       else if ( theNbNodes == 20 )  {
-        cout<<"QUADRATIC_HEXAHEDRON"<<endl;
         return VTK_QUADRATIC_HEXAHEDRON;
       }
       else if ( theNbNodes==13 || theNbNodes==15 )  {
-        cout<<"QUADRATIC - CONVEX_POINT_SET"<<endl;
         return VTK_CONVEX_POINT_SET;
       }
       else return VTK_EMPTY_CELL;
index 7f4eb32692600777ac44a74edcd4e4e2171efada..03bd30f2b87fc691d5be6580722252afa6733d5c 100644 (file)
@@ -1087,19 +1087,32 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
       if ( edge )
         Ok = const_cast<SMDS_MeshEdge*>( edge )->ChangeNodes( nodes[0], nodes[1] );
     }
+    else if ( nbnodes == 3 ) {
+      const SMDS_QuadraticEdge* edge = dynamic_cast<const SMDS_QuadraticEdge*>( elem );
+      if ( edge )
+        Ok = const_cast<SMDS_QuadraticEdge*>( edge )->ChangeNodes( nodes[0], nodes[1], nodes[2] );
+    }
     break;
   }
   case SMDSAbs_Face: {
     const SMDS_FaceOfNodes* face = dynamic_cast<const SMDS_FaceOfNodes*>( elem );
     if ( face ) {
       Ok = const_cast<SMDS_FaceOfNodes*>( face )->ChangeNodes( nodes, nbnodes );
-    } else {
-      /// ??? begin
-      const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
-      if (face) {
-        Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
+    }
+    else {
+      const SMDS_QuadraticFaceOfNodes* QF =
+        dynamic_cast<const SMDS_QuadraticFaceOfNodes*>( elem );
+      if ( QF ) {
+        Ok = const_cast<SMDS_QuadraticFaceOfNodes*>( QF )->ChangeNodes( nodes, nbnodes );
+      }
+      else {
+        /// ??? begin
+        const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
+        if (face) {
+          Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
+        }
+        /// ??? end
       }
-      /// ??? end
     }
     break;
   }
@@ -1112,8 +1125,15 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
   //}
   case SMDSAbs_Volume: {
     const SMDS_VolumeOfNodes* vol = dynamic_cast<const SMDS_VolumeOfNodes*>( elem );
-    if ( vol )
+    if ( vol ) {
       Ok = const_cast<SMDS_VolumeOfNodes*>( vol )->ChangeNodes( nodes, nbnodes );
+    }
+    else {
+      const SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<const SMDS_QuadraticVolumeOfNodes*>( elem );
+      if ( QV ) {
+        Ok = const_cast<SMDS_QuadraticVolumeOfNodes*>( QV )->ChangeNodes( nodes, nbnodes );
+      }
+    }
     break;
   }
   default:
@@ -1203,6 +1223,7 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
   return Ok;
 }
 
+
 //=======================================================================
 //function : FindEdge
 //purpose  :
@@ -1210,54 +1231,95 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
 
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
 {
-       const SMDS_MeshNode * node1=FindNode(idnode1);
-       const SMDS_MeshNode * node2=FindNode(idnode2);
-       if((node1==NULL)||(node2==NULL)) return NULL;
-       return FindEdge(node1,node2);
+  const SMDS_MeshNode * node1=FindNode(idnode1);
+  const SMDS_MeshNode * node2=FindNode(idnode2);
+  if((node1==NULL)||(node2==NULL)) return NULL;
+  return FindEdge(node1,node2);
 }
 
 //#include "Profiler.h"
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2)
 {
-       const SMDS_MeshEdge * toReturn=NULL;
-       //PROFILER_Init();
-       //PROFILER_Set();
-       SMDS_ElemIteratorPtr it1=node1->edgesIterator();
-       //PROFILER_Get(0);
-       //PROFILER_Set();
-       while(it1->more())
-       {
-               const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *>
-                       (it1->next());
-               SMDS_ElemIteratorPtr it2=e->nodesIterator();
-               while(it2->more())
-               {
-                       if(it2->next()->GetID()==node2->GetID())
-                       {
-                               toReturn=e;
-                               break;
-                       }
-               }
-       }
-       //PROFILER_Get(1);
-       return toReturn;
+  const SMDS_MeshEdge * toReturn=NULL;
+  //PROFILER_Init();
+  //PROFILER_Set();
+  SMDS_ElemIteratorPtr it1=node1->edgesIterator();
+  //PROFILER_Get(0);
+  //PROFILER_Set();
+  while(it1->more()) {
+    const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *> (it1->next());
+    SMDS_ElemIteratorPtr it2=e->nodesIterator();
+    while(it2->more()) {
+      if(it2->next()->GetID()==node2->GetID()) {
+        toReturn = e;
+        break;
+      }
+    }
+  }
+  //PROFILER_Get(1);
+  return toReturn;
 }
 
 
+//=======================================================================
+//function : FindEdgeOrCreate
+//purpose  :
+//=======================================================================
+
 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
-       const SMDS_MeshNode * node2) 
+                                           const SMDS_MeshNode * node2) 
 {
-       SMDS_MeshEdge * toReturn=NULL;
-       toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
-       if(toReturn==NULL)      
-       {
-          toReturn=new SMDS_MeshEdge(node1,node2);
-          myEdges.Add(toReturn);
-       } 
-       return toReturn;
+  SMDS_MeshEdge * toReturn=NULL;
+  toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
+  if(toReturn==NULL) {
+    toReturn=new SMDS_MeshEdge(node1,node2);
+    myEdges.Add(toReturn);
+  } 
+  return toReturn;
+}
+
+
+//=======================================================================
+//function : FindEdge
+//purpose  :
+//=======================================================================
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
+                                         int idnode3) const
+{
+  const SMDS_MeshNode * node1=FindNode(idnode1);
+  const SMDS_MeshNode * node2=FindNode(idnode2);
+  const SMDS_MeshNode * node3=FindNode(idnode3);
+  if( (node1==NULL) || (node2==NULL)  || (node3==NULL) ) return NULL;
+  return FindEdge(node1,node2,node3);
+}
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
+                                         const SMDS_MeshNode * node2,
+                                         const SMDS_MeshNode * node3)
+{
+  const SMDS_MeshEdge * toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node1->edgesIterator();
+  while(it1->more()) {
+    const SMDS_MeshEdge * e = static_cast<const SMDS_MeshEdge *> (it1->next());
+    SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+    int tmp = 0;
+    while(it2->more()) {
+      int nID = it2->next()->GetID();
+      if( nID==node2->GetID() || nID==node3->GetID() ) {
+        tmp++;
+        if(tmp==2) {
+          toReturn = e;
+          break;
+        }
+      }
+    }
+  }
+  return toReturn;
 }
 
+
 //=======================================================================
 //function : FindFace
 //purpose  :
@@ -1266,118 +1328,219 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
        int idnode3) const
 {
-       const SMDS_MeshNode * node1=FindNode(idnode1);
-       const SMDS_MeshNode * node2=FindNode(idnode2);
-       const SMDS_MeshNode * node3=FindNode(idnode3);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
-       return FindFace(node1, node2, node3);
+  const SMDS_MeshNode * node1=FindNode(idnode1);
+  const SMDS_MeshNode * node2=FindNode(idnode2);
+  const SMDS_MeshNode * node3=FindNode(idnode3);
+  if( (node1==NULL) || (node2==NULL) || (node3==NULL) ) return NULL;
+  return FindFace(node1, node2, node3);
 }
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace(
-               const SMDS_MeshNode *node1,
-               const SMDS_MeshNode *node2,
-               const SMDS_MeshNode *node3)
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3)
 {
-       const SMDS_MeshFace * face;
-       const SMDS_MeshElement * node;
-       bool node2found, node3found;
-
-       SMDS_ElemIteratorPtr it1=node1->facesIterator();
-       while(it1->more())
-       {
-               face=static_cast<const SMDS_MeshFace*>(it1->next());
-               if(face->NbNodes()!=3) continue;
-               SMDS_ElemIteratorPtr it2=face->nodesIterator();
-               node2found=false;
-               node3found=false;
-               while(it2->more())
-               {
-                       node=it2->next();
-                       if(node->GetID()==node2->GetID()) node2found=true;
-                       if(node->GetID()==node3->GetID()) node3found=true;
-               }
-               if(node2found&&node3found)
-                       return face;
-       }
-       return NULL;
+  const SMDS_MeshFace * face;
+  const SMDS_MeshElement * node;
+  bool node2found, node3found;
+
+  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  while(it1->more()) {
+    face = static_cast<const SMDS_MeshFace*>(it1->next());
+    if(face->NbNodes()!=3) continue;
+    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
+    node2found = false;
+    node3found = false;
+    while(it2->more()) {
+      node = it2->next();
+      if(node->GetID()==node2->GetID()) node2found = true;
+      if(node->GetID()==node3->GetID()) node3found = true;
+    }
+    if( node2found && node3found )
+      return face;
+  }
+  return NULL;
 }
 
-SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
-               const SMDS_MeshNode *node1,
-               const SMDS_MeshNode *node2,
-               const SMDS_MeshNode *node3)
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+                                           const SMDS_MeshNode *node2,
+                                           const SMDS_MeshNode *node3)
 {
-       SMDS_MeshFace * toReturn=NULL;
-       toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
-       if(toReturn==NULL)
-       {
-         toReturn=createTriangle(node1,node2,node3);
-       }
-       return toReturn;
+  SMDS_MeshFace * toReturn=NULL;
+  toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
+  if(toReturn==NULL) {
+    toReturn = createTriangle(node1,node2,node3);
+  }
+  return toReturn;
 }
 
+
 //=======================================================================
 //function : FindFace
 //purpose  :
 //=======================================================================
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, int idnode3,
-       int idnode4) const
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+                                         int idnode3, int idnode4) const
 {
-       const SMDS_MeshNode * node1=FindNode(idnode1);
-       const SMDS_MeshNode * node2=FindNode(idnode2);
-       const SMDS_MeshNode * node3=FindNode(idnode3);
-       const SMDS_MeshNode * node4=FindNode(idnode4);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)) return NULL;
-       return FindFace(node1, node2, node3, node4);
+  const SMDS_MeshNode * node1=FindNode(idnode1);
+  const SMDS_MeshNode * node2=FindNode(idnode2);
+  const SMDS_MeshNode * node3=FindNode(idnode3);
+  const SMDS_MeshNode * node4=FindNode(idnode4);
+  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) )
+    return NULL;
+  return FindFace(node1, node2, node3, node4);
 }
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace(
-               const SMDS_MeshNode *node1,
-               const SMDS_MeshNode *node2,
-               const SMDS_MeshNode *node3,
-               const SMDS_MeshNode *node4)
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3,
+                                         const SMDS_MeshNode *node4)
 {
-       const SMDS_MeshFace * face;
-       const SMDS_MeshElement * node;
-       bool node2found, node3found, node4found;
-       SMDS_ElemIteratorPtr it1=node1->facesIterator();
-       while(it1->more())
-       {
-               face=static_cast<const SMDS_MeshFace *>(it1->next());
-               if(face->NbNodes()!=4) continue;
-               SMDS_ElemIteratorPtr it2=face->nodesIterator();
-               node2found=false;
-               node3found=false;
-               node4found=false;
-               while(it2->more())
-               {
-                       node=it2->next();
-                       if(node->GetID()==node2->GetID()) node2found=true;
-                       if(node->GetID()==node3->GetID()) node3found=true;
-                       if(node->GetID()==node4->GetID()) node4found=true;
-               }
-               if(node2found&&node3found&&node4found)
-                       return face;
-       }
-       return NULL;
+  const SMDS_MeshFace * face;
+  const SMDS_MeshElement * node;
+  bool node2found, node3found, node4found;
+  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  while(it1->more()) {
+    face = static_cast<const SMDS_MeshFace *>(it1->next());
+    if(face->NbNodes()!=4) continue;
+    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
+    node2found = false;
+    node3found = false;
+    node4found = false;
+    while(it2->more()) {
+      node=it2->next();
+      if(node->GetID()==node2->GetID()) node2found = true;
+      if(node->GetID()==node3->GetID()) node3found = true;
+      if(node->GetID()==node4->GetID()) node4found = true;
+    }
+    if( node2found && node3found && node4found )
+      return face;
+  }
+  return NULL;
 }
 
-SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
-               const SMDS_MeshNode *node1,
-               const SMDS_MeshNode *node2,
-               const SMDS_MeshNode *node3,
-               const SMDS_MeshNode *node4)
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+                                           const SMDS_MeshNode *node2,
+                                           const SMDS_MeshNode *node3,
+                                           const SMDS_MeshNode *node4)
 {
-       SMDS_MeshFace * toReturn=NULL;
-       toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
-       if(toReturn==NULL)
-       {
-         toReturn=createQuadrangle(node1,node2,node3,node4);
-       }
-       return toReturn;
+  SMDS_MeshFace * toReturn=NULL;
+  toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
+  if(toReturn==NULL) {
+    toReturn=createQuadrangle(node1,node2,node3,node4);
+  }
+  return toReturn;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose  :quadratic triangle
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+                                         int idnode3, int idnode4,
+                                         int idnode5, int idnode6) const
+{
+  const SMDS_MeshNode * node1 = FindNode(idnode1);
+  const SMDS_MeshNode * node2 = FindNode(idnode2);
+  const SMDS_MeshNode * node3 = FindNode(idnode3);
+  const SMDS_MeshNode * node4 = FindNode(idnode4);
+  const SMDS_MeshNode * node5 = FindNode(idnode5);
+  const SMDS_MeshNode * node6 = FindNode(idnode6);
+  if( (node1==NULL) || (node2==NULL) || (node3==NULL) ||
+      (node4==NULL) || (node5==NULL) || (node6==NULL) ) return NULL;
+  return FindFace(node1, node2, node3, node4, node5, node6);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3,
+                                         const SMDS_MeshNode *node4,
+                                         const SMDS_MeshNode *node5,
+                                         const SMDS_MeshNode *node6)
+{
+  const SMDS_MeshFace * face;
+  const SMDS_MeshElement * node;
+  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  while(it1->more()) {
+    face = static_cast<const SMDS_MeshFace*>(it1->next());
+    if(face->NbNodes()!=6) continue;
+    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
+    int tmp = 0;
+    while(it2->more()) {
+      node = it2->next();
+      if(node->GetID()==node2->GetID()) tmp++;
+      if(node->GetID()==node3->GetID()) tmp++;
+      if(node->GetID()==node4->GetID()) tmp++;
+      if(node->GetID()==node5->GetID()) tmp++;
+      if(node->GetID()==node6->GetID()) tmp++;
+    }
+    if( tmp==5 )
+      return static_cast<const SMDS_MeshFace*>(face);
+  }
+  return NULL;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose  : quadratic quadrangle
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+                                         int idnode3, int idnode4,
+                                         int idnode5, int idnode6,
+                                         int idnode7, int idnode8) const
+{
+  const SMDS_MeshNode * node1 = FindNode(idnode1);
+  const SMDS_MeshNode * node2 = FindNode(idnode2);
+  const SMDS_MeshNode * node3 = FindNode(idnode3);
+  const SMDS_MeshNode * node4 = FindNode(idnode4);
+  const SMDS_MeshNode * node5 = FindNode(idnode5);
+  const SMDS_MeshNode * node6 = FindNode(idnode6);
+  const SMDS_MeshNode * node7 = FindNode(idnode7);
+  const SMDS_MeshNode * node8 = FindNode(idnode8);
+  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) ||
+      (node5==NULL) || (node6==NULL) || (node7==NULL) || (node8==NULL) )
+    return NULL;
+  return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3,
+                                         const SMDS_MeshNode *node4,
+                                         const SMDS_MeshNode *node5,
+                                         const SMDS_MeshNode *node6,
+                                         const SMDS_MeshNode *node7,
+                                         const SMDS_MeshNode *node8)
+{
+  const SMDS_MeshFace * face;
+  const SMDS_MeshElement * node;
+  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  while(it1->more()) {
+    face = static_cast<const SMDS_MeshFace *>(it1->next());
+    if(face->NbNodes()!=8) continue;
+    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
+    int tmp = 0;
+    while(it2->more()) {
+      node = it2->next();
+      if(node->GetID()==node2->GetID()) tmp++;
+      if(node->GetID()==node3->GetID()) tmp++;
+      if(node->GetID()==node4->GetID()) tmp++;
+      if(node->GetID()==node5->GetID()) tmp++;
+      if(node->GetID()==node6->GetID()) tmp++;
+      if(node->GetID()==node7->GetID()) tmp++;
+      if(node->GetID()==node8->GetID()) tmp++;
+    }
+    if( tmp==7 )
+      return face;
+  }
+  return NULL;
 }
 
+
 //=======================================================================
 //function : FindElement
 //purpose  :
@@ -1385,7 +1548,7 @@ SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
 
 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 {
-       return myElementIDFactory->MeshElement(IDelem);
+  return myElementIDFactory->MeshElement(IDelem);
 }
 
 //=======================================================================
index 2dad43052e0d6d37c04a86a1506bc0009918cb67..f0835eae355e8b569f394741dffa3f5b33185c87 100644 (file)
@@ -378,7 +378,7 @@ public:
                                           const SMDS_MeshNode * n12,
                                           const SMDS_MeshNode * n23,
                                           const SMDS_MeshNode * n34,
-                                          const SMDS_MeshNode * n51, 
+                                          const SMDS_MeshNode * n41, 
                                           const SMDS_MeshNode * n56,
                                           const SMDS_MeshNode * n67,
                                           const SMDS_MeshNode * n78,
@@ -399,7 +399,7 @@ public:
                                      const SMDS_MeshNode * n12,
                                      const SMDS_MeshNode * n23,
                                      const SMDS_MeshNode * n34,
-                                     const SMDS_MeshNode * n51, 
+                                     const SMDS_MeshNode * n41, 
                                      const SMDS_MeshNode * n56,
                                      const SMDS_MeshNode * n67,
                                      const SMDS_MeshNode * n78,
@@ -456,11 +456,19 @@ public:
 
   const SMDS_MeshNode *FindNode(int idnode) const;
   const SMDS_MeshEdge *FindEdge(int idnode1, int idnode2) const;
+  const SMDS_MeshEdge *FindEdge(int idnode1, int idnode2, int idnode3) const;
   const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3) const;
   const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3, int idnode4) const;
+  const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3,
+                                int idnode4, int idnode5, int idnode6) const;
+  const SMDS_MeshFace *FindFace(int idnode1, int idnode2, int idnode3, int idnode4,
+                                int idnode5, int idnode6, int idnode7, int idnode8) const;
   const SMDS_MeshElement *FindElement(int IDelem) const;
   static const SMDS_MeshEdge* FindEdge(const SMDS_MeshNode * n1,
                                        const SMDS_MeshNode * n2);
+  static const SMDS_MeshEdge* FindEdge(const SMDS_MeshNode * n1,
+                                       const SMDS_MeshNode * n2,
+                                       const SMDS_MeshNode * n3);
   static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1,
                                        const SMDS_MeshNode *n2,
                                        const SMDS_MeshNode *n3);
@@ -468,6 +476,20 @@ public:
                                        const SMDS_MeshNode *n2,
                                        const SMDS_MeshNode *n3,
                                        const SMDS_MeshNode *n4);
+  static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1,
+                                       const SMDS_MeshNode *n2,
+                                       const SMDS_MeshNode *n3,
+                                       const SMDS_MeshNode *n4,
+                                       const SMDS_MeshNode *n5,
+                                       const SMDS_MeshNode *n6);
+  static const SMDS_MeshFace* FindFace(const SMDS_MeshNode *n1,
+                                       const SMDS_MeshNode *n2,
+                                       const SMDS_MeshNode *n3,
+                                       const SMDS_MeshNode *n4,
+                                       const SMDS_MeshNode *n5,
+                                       const SMDS_MeshNode *n6,
+                                       const SMDS_MeshNode *n7,
+                                       const SMDS_MeshNode *n8);
 
   const SMDS_MeshFace *FindFace(std::vector<int> nodes_ids) const;
   static const SMDS_MeshFace* FindFace(std::vector<const SMDS_MeshNode *> nodes);
index f2df1fd892e691882a227a35fdb17415153e91b1..518feb1adc5ce2c5cec2e47fcc0ff2debdb68585 100644 (file)
@@ -218,7 +218,7 @@ bool SMDS_MeshElement::IsQuadratic() const
   return false;
 }
 
-bool SMDS_MeshElement::IsMediumNode(class SMDS_MeshNode* node) const
+bool SMDS_MeshElement::IsMediumNode(const SMDS_MeshNode* node) const
 {
   return false;
 }
index 4ba69f7ab8d18e5093b6f784cd33d0d22be7aab1..e8672cd908ce8f7d2cee327022919bbd9292c410 100644 (file)
@@ -82,7 +82,7 @@ public:
   virtual bool IsPoly() const { return false; };
   virtual bool IsQuadratic() const;
 
-  virtual bool IsMediumNode(class SMDS_MeshNode* node) const;
+  virtual bool IsMediumNode(const SMDS_MeshNode* node) const;
 
   friend std::ostream & operator <<(std::ostream & OS, const SMDS_MeshElement *);
   friend bool SMDS_MeshElementIDFactory::BindID(int ID,SMDS_MeshElement*elem);
index 817d3ceb4bb7e5dac9cc766c3b74a43e9fd9453c..9f35e015818776d4b5f64f2383a56492ebdd2086 100644 (file)
@@ -970,7 +970,8 @@ bool SMDS_VolumeTool::GetFaceNormal (int faceIndex, double & X, double & Y, doub
   XYZ aVec13( p3 - p1 );
   XYZ cross = aVec12.Crossed( aVec13 );
 
-  if ( myFaceNbNodes == 4 ) {
+  //if ( myFaceNbNodes == 4 ) {
+  if ( myFaceNbNodes >3 ) {
     XYZ p4 ( myFaceNodes[3] );
     XYZ aVec14( p4 - p1 );
     XYZ cross2 = aVec13.Crossed( aVec14 );
@@ -1106,7 +1107,7 @@ bool SMDS_VolumeTool::IsLinked (const SMDS_MeshNode* theNode1,
 bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
                                 const int theNode2Index) const
 {
-  if (myVolume->IsPoly()) {
+  if ( myVolume->IsPoly() ) {
     return IsLinked(myVolumeNodes[theNode1Index], myVolumeNodes[theNode2Index]);
   }
 
@@ -1144,6 +1145,57 @@ bool SMDS_VolumeTool::IsLinked (const int theNode1Index,
     default:;
     }
     break;
+  case 10:
+    {
+      switch ( minInd ) {
+      case 0: if( maxInd==4 ||  maxInd==6 ||  maxInd==7 ) return true;
+      case 1: if( maxInd==4 ||  maxInd==5 ||  maxInd==8 ) return true;
+      case 2: if( maxInd==5 ||  maxInd==6 ||  maxInd==9 ) return true;
+      case 3: if( maxInd==7 ||  maxInd==8 ||  maxInd==9 ) return true;
+      default:;
+      }
+      break;
+    }
+  case 13:
+    {
+      switch ( minInd ) {
+      case 0: if( maxInd==5 ||  maxInd==8 ||  maxInd==9 ) return true;
+      case 1: if( maxInd==5 ||  maxInd==6 ||  maxInd==10 ) return true;
+      case 2: if( maxInd==6 ||  maxInd==7 ||  maxInd==11 ) return true;
+      case 3: if( maxInd==7 ||  maxInd==8 ||  maxInd==12 ) return true;
+      case 4: if( maxInd==9 ||  maxInd==10 ||  maxInd==11 ||  maxInd==12 ) return true;
+      default:;
+      }
+      break;
+    }
+  case 15:
+    {
+      switch ( minInd ) {
+      case 0: if( maxInd==6 ||  maxInd==8 ||  maxInd==12 ) return true;
+      case 1: if( maxInd==6 ||  maxInd==7 ||  maxInd==13 ) return true;
+      case 2: if( maxInd==7 ||  maxInd==8 ||  maxInd==14 ) return true;
+      case 3: if( maxInd==9 ||  maxInd==11 ||  maxInd==12 ) return true;
+      case 4: if( maxInd==9 ||  maxInd==10 ||  maxInd==13 ) return true;
+      case 5: if( maxInd==10 ||  maxInd==11 ||  maxInd==14 ) return true;
+      default:;
+      }
+      break;
+    }
+  case 20:
+    {
+      switch ( minInd ) {
+      case 0: if( maxInd==8 ||  maxInd==11 ||  maxInd==16 ) return true;
+      case 1: if( maxInd==8 ||  maxInd==9 ||  maxInd==17 ) return true;
+      case 2: if( maxInd==9 ||  maxInd==10 ||  maxInd==18 ) return true;
+      case 3: if( maxInd==10 ||  maxInd==11 ||  maxInd==19 ) return true;
+      case 4: if( maxInd==12 ||  maxInd==15 ||  maxInd==16 ) return true;
+      case 5: if( maxInd==12 ||  maxInd==13 ||  maxInd==17 ) return true;
+      case 6: if( maxInd==13 ||  maxInd==14 ||  maxInd==18 ) return true;
+      case 7: if( maxInd==14 ||  maxInd==15 ||  maxInd==19 ) return true;
+      default:;
+      }
+      break;
+    }
   default:;
   }
   return false;
@@ -1185,8 +1237,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
   typedef map< const SMDS_MeshElement*, int > TElemIntMap;
   TElemIntMap volNbShared;
   TElemIntMap::iterator vNbIt;
-  for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
-  {
+  for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
     const SMDS_MeshNode* n = nodes[ iNode ];
     SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator();
     while ( eIt->more() ) {
@@ -1194,10 +1245,12 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
       if ( elem != myVolume && elem->GetType() == SMDSAbs_Volume ) {
         int nbShared = 1;
         vNbIt = volNbShared.find( elem );
-        if ( vNbIt == volNbShared.end() )
+        if ( vNbIt == volNbShared.end() ) {
           volNbShared.insert ( TElemIntMap::value_type( elem, nbShared ));
-        else
+        }
+        else {
           nbShared = ++(*vNbIt).second;
+        }
         if ( nbShared > maxNbShared )
           maxNbShared = nbShared;
       }
@@ -1213,8 +1266,7 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
   if ( IsFaceExternal( faceIndex ))
     intNormal = XYZ( -intNormal.x, -intNormal.y, -intNormal.z );
   XYZ p0 ( nodes[0] ), baryCenter;
-  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ )
-  {
+  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
     int nbShared = (*vNbIt).second;
     if ( nbShared >= 3 ) {
       SMDS_VolumeTool volume( (*vNbIt).first );
@@ -1226,20 +1278,20 @@ bool SMDS_VolumeTool::IsFreeFace( int faceIndex )
     // remove a volume from volNbShared map
     volNbShared.erase( vNbIt );
   }
+
   // here volNbShared contains only volumes laying on the
   // opposite side of the face
-  if ( volNbShared.empty() )
+  if ( volNbShared.empty() ) {
     return free; // is free
+  }
 
   // check if the whole area of a face is shared
   bool isShared[] = { false, false, false, false }; // 4 triangle parts of a quadrangle
-  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ )
-  {
+  for ( vNbIt = volNbShared.begin(); vNbIt != volNbShared.end(); vNbIt++ ) {
     SMDS_VolumeTool volume( (*vNbIt).first );
     bool prevLinkShared = false;
     int nbSharedLinks = 0;
-    for ( int iNode = 0; iNode < nbFaceNodes; iNode++ )
-    {
+    for ( int iNode = 0; iNode < nbFaceNodes; iNode++ ) {
       bool linkShared = volume.IsLinked( nodes[ iNode ], nodes[ iNode + 1] );
       if ( linkShared )
         nbSharedLinks++;
index d1084f7d4f75394c1c6327a1ad61a592a5af81fb..ea44619be6a57307f333dada2b3bb52d5ee64026 100644 (file)
@@ -29,7 +29,7 @@
 using namespace std;
 #include "SMESH_2D_Algo.hxx"
 #include "SMESH_Gen.hxx"
-#include "SMESH_subMesh.hxx"
+#include <TopExp.hxx>
 
 #include "utilities.h"
 
@@ -45,6 +45,7 @@ SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen)
 //   _compatibleHypothesis.push_back("hypothese_2D_bidon");
   _type = ALGO_2D;
   gen->_map2D_Algo[hypId] = this;
+  myCreateQuadratic = false;
 }
 
 //=============================================================================
@@ -55,6 +56,7 @@ SMESH_2D_Algo::SMESH_2D_Algo(int hypId, int studyId, SMESH_Gen* gen)
 
 SMESH_2D_Algo::~SMESH_2D_Algo()
 {
+  myCreateQuadratic = false;
 }
 
 //=============================================================================
@@ -80,13 +82,16 @@ int SMESH_2D_Algo::NumberOfWires(const TopoDS_Shape& S)
 int SMESH_2D_Algo::NumberOfPoints(SMESH_Mesh& aMesh, const TopoDS_Wire& W)
 {
   int nbPoints = 0;
-  for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next())
-    {
-      const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
-      int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
-      //SCRUTE(nb);
-      nbPoints += nb +1; // internal points plus 1 vertex of 2 (last point ?)
-    }
+  for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) {
+    const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
+    int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
+    if(myCreateQuadratic)
+      nb = nb/2;
+    //SCRUTE(nb);
+    nbPoints += nb +1; // internal points plus 1 vertex of 2 (last point ?)
+  }
   //SCRUTE(nbPoints);
   return nbPoints;
 }
+
+
index 5c904e22ef89ea1366a1c566a2f58c2ec647246e..65857fced165a7026b6e788b8a3d8efd5aca6a33 100644 (file)
@@ -30,7 +30,8 @@
 #define _SMESH_2D_ALGO_HXX_
 
 #include "SMESH_Algo.hxx"
-#include <TopoDS_Wire.hxx>
+#include "SMESH_subMesh.hxx"
+#include "TopoDS_Wire.hxx"
 
 class SMESH_2D_Algo:
   public SMESH_Algo
@@ -41,6 +42,9 @@ public:
 
   int NumberOfWires(const TopoDS_Shape& S);
   int NumberOfPoints(SMESH_Mesh& aMesh,const TopoDS_Wire& W);
+
+protected:
+  bool myCreateQuadratic;
 };
 
 #endif
index d42680f62e998d457ebb7edff47d49c1b2ac19e0..6a05c16af75349e963213a1cf7d0410bf05f3929 100644 (file)
@@ -29,7 +29,6 @@
 using namespace std;
 #include "SMESH_3D_Algo.hxx"
 #include "SMESH_Gen.hxx"
-#include "SMESH_subMesh.hxx"
 
 #include "utilities.h"
 
@@ -56,3 +55,5 @@ SMESH_3D_Algo::SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen)
 SMESH_3D_Algo::~SMESH_3D_Algo()
 {
 }
+
+
index 62621ce3cf532645b7efa60e9a9279206790451a..21c53ca0f595ad788b87df66302b390d80820a1a 100644 (file)
@@ -37,6 +37,7 @@ class SMESH_3D_Algo:
 public:
   SMESH_3D_Algo(int hypId, int studyId, SMESH_Gen* gen);
   virtual ~SMESH_3D_Algo();
+
 };
 
 #endif
index 12c72d828f284a56bb442fa84c4cf1128e63b3c9..5acc2b242b5d7db961891978f3cb5239b7d91c3c 100644 (file)
 
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Edge.hxx>
+#include <gp_XY.hxx>
 
 #include <string>
 #include <vector>
 #include <list>
+#include <map>
 
 class SMESH_Gen;
 class SMESH_Mesh;
 class TopoDS_Face;
 class SMESHDS_Mesh;
+class SMDS_MeshNode;
 
 class SMESH_Algo:public SMESH_Hypothesis
 {
@@ -97,6 +100,7 @@ class SMESH_Algo:public SMESH_Hypothesis
         std::vector<std::string> _compatibleHypothesis;
         std::list<const SMESHDS_Hypothesis *> _appliedHypList;
         std::list<const SMESHDS_Hypothesis *> _usedHypList;
+
 };
 
 #endif
index ffd77cd554fe8536a9860f2b0e4cf242b6e7e651..f36f08964b2b7780b2700af28de688664e396c9e 100644 (file)
@@ -861,7 +861,8 @@ int SMESH_Mesh::NbTriangles() throw(SALOME_Exception)
   const SMDS_MeshFace * curFace;
   while (itFaces->more()) {
     curFace = itFaces->next();
-    if (!curFace->IsPoly() && curFace->NbNodes() == 3) Nb++;
+    if ( !curFace->IsPoly() && 
+        ( curFace->NbNodes()==3 || curFace->NbNodes()==6 ) ) Nb++;
   }
   return Nb;
 }
@@ -879,7 +880,8 @@ int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception)
   const SMDS_MeshFace * curFace;
   while (itFaces->more()) {
     curFace = itFaces->next();
-    if (!curFace->IsPoly() && curFace->NbNodes() == 4) Nb++;
+    if ( !curFace->IsPoly() && 
+        ( curFace->NbNodes() == 4 || curFace->NbNodes()==8 ) ) Nb++;
   }
   return Nb;
 }
@@ -917,7 +919,8 @@ int SMESH_Mesh::NbTetras() throw(SALOME_Exception)
   const SMDS_MeshVolume * curVolume;
   while (itVolumes->more()) {
     curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 4) Nb++;
+    if ( !curVolume->IsPoly() && 
+        ( curVolume->NbNodes() == 4 || curVolume->NbNodes()==10 ) ) Nb++;
   }
   return Nb;
 }
@@ -931,7 +934,8 @@ int SMESH_Mesh::NbHexas() throw(SALOME_Exception)
   const SMDS_MeshVolume * curVolume;
   while (itVolumes->more()) {
     curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 8) Nb++;
+    if ( !curVolume->IsPoly() && 
+        ( curVolume->NbNodes() == 8 || curVolume->NbNodes()==20 ) ) Nb++;
   }
   return Nb;
 }
@@ -945,7 +949,8 @@ int SMESH_Mesh::NbPyramids() throw(SALOME_Exception)
   const SMDS_MeshVolume * curVolume;
   while (itVolumes->more()) {
     curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 5) Nb++;
+    if ( !curVolume->IsPoly() && 
+        ( curVolume->NbNodes() == 5 || curVolume->NbNodes()==13 ) ) Nb++;
   }
   return Nb;
 }
@@ -959,7 +964,8 @@ int SMESH_Mesh::NbPrisms() throw(SALOME_Exception)
   const SMDS_MeshVolume * curVolume;
   while (itVolumes->more()) {
     curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 6) Nb++;
+    if ( !curVolume->IsPoly() && 
+        ( curVolume->NbNodes() == 6 || curVolume->NbNodes()==15 ) ) Nb++;
   }
   return Nb;
 }
index d75adf3e730c4426cf38fd9617b9c7c2dc2cc0a3..ea1334bfb7c68831b43253e6f860e70a3db81623 100644 (file)
@@ -34,6 +34,7 @@
 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
+#include "SMDS_QuadraticFaceOfNodes.hxx"
 
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Mesh.hxx"
@@ -75,8 +76,12 @@ typedef map<const SMDS_MeshElement*, list<const SMDS_MeshNode*> >    TElemOfNode
 typedef map<const SMDS_MeshElement*, list<const SMDS_MeshElement*> > TElemOfElemListMap;
 typedef map<const SMDS_MeshNode*, list<const SMDS_MeshNode*> >       TNodeOfNodeListMap;
 typedef TNodeOfNodeListMap::iterator                                 TNodeOfNodeListMapItr;
+//typedef map<const SMDS_MeshNode*, vector<const SMDS_MeshNode*> >     TNodeOfNodeVecMap;
+//typedef TNodeOfNodeVecMap::iterator                                  TNodeOfNodeVecMapItr;
 typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeListMapItr> > TElemOfVecOfNnlmiMap;
+//typedef map<const SMDS_MeshElement*, vector<TNodeOfNodeVecMapItr> >  TElemOfVecOfMapNodesMap;
 
+typedef pair<const SMDS_MeshNode*, const SMDS_MeshNode*> NLink;
 
 //=======================================================================
 //function : SMESH_MeshEditor
@@ -102,8 +107,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs,
   set< SMESH_subMesh *> smmap;
 
   list<int>::const_iterator it = theIDs.begin();
-  for ( ; it != theIDs.end(); it++ )
-  {
+  for ( ; it != theIDs.end(); it++ ) {
     const SMDS_MeshElement * elem;
     if ( isNodes )
       elem = aMesh->FindNode( *it );
@@ -114,8 +118,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs,
 
     // Find sub-meshes to notify about modification
     SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
-    while ( nodeIt->more() )
-    {
+    while ( nodeIt->more() ) {
       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
       const SMDS_PositionPtr& aPosition = node->GetPosition();
       if ( aPosition.get() ) {
@@ -142,6 +145,7 @@ bool SMESH_MeshEditor::Remove (const list< int >& theIDs,
     for ( smIt = smmap.begin(); smIt != smmap.end(); smIt++ )
       (*smIt)->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
   }
+
   return true;
 }
 
@@ -157,8 +161,7 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
   if ( aMesh->ShapeToMesh().IsNull() )
     return 0;
 
-  if ( theElem->GetType() == SMDSAbs_Node )
-  {
+  if ( theElem->GetType() == SMDSAbs_Node ) {
     const SMDS_PositionPtr& aPosition =
       static_cast<const SMDS_MeshNode*>( theElem )->GetPosition();
     if ( aPosition.get() )
@@ -169,25 +172,22 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
 
   TopoDS_Shape aShape; // the shape a node is on
   SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
-  while ( nodeIt->more() )
-  {
+  while ( nodeIt->more() ) {
     const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
     const SMDS_PositionPtr& aPosition = node->GetPosition();
     if ( aPosition.get() ) {
-        int aShapeID = aPosition->GetShapeId();
-        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 = aPosition->GetShapeId();
+      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 );
       }
+    }
   }
 
   // None of nodes is on a proper shape,
@@ -197,17 +197,89 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
     return 0;
   }
   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() );
+  for ( ; ancIt.More(); ancIt.Next() ) {
+    SMESHDS_SubMesh * sm = aMesh->MeshElements( ancIt.Value() );
+    if ( sm && sm->Contains( theElem ))
+      return aMesh->ShapeToIndex( ancIt.Value() );
   }
 
   //MESSAGE ("::FindShape() - SHAPE NOT FOUND")
   return 0;
 }
 
+//=======================================================================
+//function : ShiftNodesQuadTria
+//purpose  : auxilary
+//           Shift nodes in the array corresponded to quadratic triangle
+//           example: (0,1,2,3,4,5) -> (1,2,0,4,5,3)
+//=======================================================================
+static void ShiftNodesQuadTria(const SMDS_MeshNode* aNodes[])
+{
+  const SMDS_MeshNode* nd1 = aNodes[0];
+  aNodes[0] = aNodes[1];
+  aNodes[1] = aNodes[2];
+  aNodes[2] = nd1;
+  const SMDS_MeshNode* nd2 = aNodes[3];
+  aNodes[3] = aNodes[4];
+  aNodes[4] = aNodes[5];
+  aNodes[5] = nd2;
+}
+
+//=======================================================================
+//function : GetNodesFromTwoTria
+//purpose  : auxilary
+//           Shift nodes in the array corresponded to quadratic triangle
+//           example: (0,1,2,3,4,5) -> (1,2,0,4,5,3)
+//=======================================================================
+static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1,
+                                const SMDS_MeshElement * theTria2,
+                                const SMDS_MeshNode* N1[],
+                                const SMDS_MeshNode* N2[])
+{
+  SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
+  int i=0;
+  while(i<6) {
+    N1[i] = static_cast<const SMDS_MeshNode*>( it->next() );
+    i++;
+  }
+  if(it->more()) return false;
+  it = theTria2->nodesIterator();
+  i=0;
+  while(i<6) {
+    N2[i] = static_cast<const SMDS_MeshNode*>( it->next() );
+    i++;
+  }
+  if(it->more()) return false;
+
+  int sames[3] = {-1,-1,-1};
+  int nbsames = 0;
+  int j;
+  for(i=0; i<3; i++) {
+    for(j=0; j<3; j++) {
+      if(N1[i]==N2[j]) {
+        sames[i] = j;
+        nbsames++;
+        break;
+      }
+    }
+  }
+  if(nbsames!=2) return false;
+  if(sames[0]>-1) {
+    ShiftNodesQuadTria(N1);
+    if(sames[1]>-1) {
+      ShiftNodesQuadTria(N1);
+    }
+  }
+  i = sames[0] + sames[1] + sames[2];
+  for(; i<2; i++) {
+    ShiftNodesQuadTria(N2);
+  }
+  // now we receive following N1 and N2 (using numeration as above image)
+  // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6) 
+  // i.e. first nodes from both arrays determ new diagonal
+  return true;
+}
+
 //=======================================================================
 //function : InverseDiag
 //purpose  : Replace two neighbour triangles with ones built on the same 4 nodes
@@ -220,71 +292,116 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
 {
   if (!theTria1 || !theTria2)
     return false;
+
   const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( theTria1 );
-  if (!F1) return false;
   const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( theTria2 );
-  if (!F2) return false;
+  if (F1 && F2) {
 
-  //  1 +--+ A  theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
-  //    | /|    theTria2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
-  //    |/ |                                         | \|
-  //  B +--+ 2                                     B +--+ 2
+    //  1 +--+ A  theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
+    //    | /|    theTria2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
+    //    |/ |                                         | \|
+    //  B +--+ 2                                     B +--+ 2
 
-  // put nodes in array and find out indices of the same ones
-  const SMDS_MeshNode* aNodes [6];
-  int sameInd [] = { 0, 0, 0, 0, 0, 0 };
-  int i = 0;
-  SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
-  while ( it->more() )
-  {
-    aNodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
-
-    if ( i > 2 ) // theTria2
-      // find same node of theTria1
-      for ( int j = 0; j < 3; j++ )
-        if ( aNodes[ i ] == aNodes[ j ]) {
-          sameInd[ j ] = i;
-          sameInd[ i ] = j;
-          break;
-        }
-    // next
-    i++;
-    if ( i == 3 ) {
-      if ( it->more() )
-        return false; // theTria1 is not a triangle
-      it = theTria2->nodesIterator();
+    // put nodes in array and find out indices of the same ones
+    const SMDS_MeshNode* aNodes [6];
+    int sameInd [] = { 0, 0, 0, 0, 0, 0 };
+    int i = 0;
+    SMDS_ElemIteratorPtr it = theTria1->nodesIterator();
+    while ( it->more() ) {
+      aNodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
+      
+      if ( i > 2 ) // theTria2
+        // find same node of theTria1
+        for ( int j = 0; j < 3; j++ )
+          if ( aNodes[ i ] == aNodes[ j ]) {
+            sameInd[ j ] = i;
+            sameInd[ i ] = j;
+            break;
+          }
+      // next
+      i++;
+      if ( i == 3 ) {
+        if ( it->more() )
+          return false; // theTria1 is not a triangle
+        it = theTria2->nodesIterator();
+      }
+      if ( i == 6 && it->more() )
+        return false; // theTria2 is not a triangle
     }
-    if ( i == 6 && it->more() )
-      return false; // theTria2 is not a triangle
-  }
+    
+    // find indices of 1,2 and of A,B in theTria1
+    int iA = 0, iB = 0, i1 = 0, i2 = 0;
+    for ( i = 0; i < 6; i++ ) {
+      if ( sameInd [ i ] == 0 )
+        if ( i < 3 ) i1 = i;
+        else         i2 = i;
+      else if (i < 3)
+        if ( iA ) iB = i;
+        else      iA = i;
+    }
+    // nodes 1 and 2 should not be the same
+    if ( aNodes[ i1 ] == aNodes[ i2 ] )
+      return false;
+
+    // theTria1: A->2
+    aNodes[ iA ] = aNodes[ i2 ];
+    // theTria2: B->1
+    aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
+
+    //MESSAGE( theTria1 << theTria2 );
+    
+    GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
+    GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
+    
+    //MESSAGE( theTria1 << theTria2 );
 
-  // find indices of 1,2 and of A,B in theTria1
-  int iA = 0, iB = 0, i1 = 0, i2 = 0;
-  for ( i = 0; i < 6; i++ )
-  {
-    if ( sameInd [ i ] == 0 )
-      if ( i < 3 ) i1 = i;
-      else         i2 = i;
-    else if (i < 3)
-      if ( iA ) iB = i;
-      else      iA = i;
-  }
-  // nodes 1 and 2 should not be the same
-  if ( aNodes[ i1 ] == aNodes[ i2 ] )
+    return true;
+  
+  } // end if(F1 && F2)
+
+  // check case of quadratic faces
+  const SMDS_QuadraticFaceOfNodes* QF1 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (theTria1);
+  if(!QF1) return false;
+  const SMDS_QuadraticFaceOfNodes* QF2 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (theTria2);
+  if(!QF2) return false;
+
+  //       5
+  //  1 +--+--+ 2  theTria1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
+  //    |    /|    theTria2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
+  //    |   / |  
+  //  7 +  +  + 6
+  //    | /9  |
+  //    |/    |
+  //  4 +--+--+ 3  
+  //       8
+  
+  const SMDS_MeshNode* N1 [6];
+  const SMDS_MeshNode* N2 [6];
+  if(!GetNodesFromTwoTria(theTria1,theTria2,N1,N2))
     return false;
-
-
-  // theTria1: A->2
-  aNodes[ iA ] = aNodes[ i2 ];
-  // theTria2: B->1
-  aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
-
-  //MESSAGE( theTria1 << theTria2 );
-
-  GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
-  GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
-
-  //MESSAGE( theTria1 << theTria2 );
+  // now we receive following N1 and N2 (using numeration as above image)
+  // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6) 
+  // i.e. first nodes from both arrays determ new diagonal
+
+  const SMDS_MeshNode* N1new [6];
+  const SMDS_MeshNode* N2new [6];
+  N1new[0] = N1[0];
+  N1new[1] = N2[0];
+  N1new[2] = N2[1];
+  N1new[3] = N1[4];
+  N1new[4] = N2[3];
+  N1new[5] = N1[5];
+  N2new[0] = N1[0];
+  N2new[1] = N1[1];
+  N2new[2] = N2[0];
+  N2new[3] = N1[3];
+  N2new[4] = N2[5];
+  N2new[5] = N1[4];
+  // replaces nodes in faces
+  GetMeshDS()->ChangeElementNodes( theTria1, N1new, 6 );
+  GetMeshDS()->ChangeElementNodes( theTria2, N2new, 6 );
 
   return true;
 }
@@ -318,7 +435,8 @@ static bool findTriangles(const SMDS_MeshNode *    theNode1,
       if ( theTria1 ) {
         theTria2 = elem;
         break;
-      } else {
+      }
+      else {
         theTria1 = elem;
       }
   }
@@ -342,55 +460,65 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
     return false;
 
   const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( tr1 );
-  if (!F1) return false;
+  //if (!F1) return false;
   const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( tr2 );
-  if (!F2) return false;
-
-  //  1 +--+ A  tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
-  //    | /|    tr2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
-  //    |/ |                                    | \|
-  //  B +--+ 2                                B +--+ 2
-
-  // put nodes in array
-  // and find indices of 1,2 and of A in tr1 and of B in tr2
-  int i, iA1 = 0, i1 = 0;
-  const SMDS_MeshNode* aNodes1 [3];
-  SMDS_ElemIteratorPtr it;
-  for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
-    aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
-    if ( aNodes1[ i ] == theNode1 )
-      iA1 = i; // node A in tr1
-    else if ( aNodes1[ i ] != theNode2 )
-      i1 = i;  // node 1
-  }
-  int iB2 = 0, i2 = 0;
-  const SMDS_MeshNode* aNodes2 [3];
-  for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
-    aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
-    if ( aNodes2[ i ] == theNode2 )
-      iB2 = i; // node B in tr2
-    else if ( aNodes2[ i ] != theNode1 )
-      i2 = i;  // node 2
-  }
-
-  // nodes 1 and 2 should not be the same
-  if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
-    return false;
-
-  // tr1: A->2
-  aNodes1[ iA1 ] = aNodes2[ i2 ];
-  // tr2: B->1
-  aNodes2[ iB2 ] = aNodes1[ i1 ];
+  //if (!F2) return false;
+  if (F1 && F2) {
+
+    //  1 +--+ A  tr1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
+    //    | /|    tr2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
+    //    |/ |                                    | \|
+    //  B +--+ 2                                B +--+ 2
+
+    // put nodes in array
+    // and find indices of 1,2 and of A in tr1 and of B in tr2
+    int i, iA1 = 0, i1 = 0;
+    const SMDS_MeshNode* aNodes1 [3];
+    SMDS_ElemIteratorPtr it;
+    for (i = 0, it = tr1->nodesIterator(); it->more(); i++ ) {
+      aNodes1[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
+      if ( aNodes1[ i ] == theNode1 )
+        iA1 = i; // node A in tr1
+      else if ( aNodes1[ i ] != theNode2 )
+        i1 = i;  // node 1
+    }
+    int iB2 = 0, i2 = 0;
+    const SMDS_MeshNode* aNodes2 [3];
+    for (i = 0, it = tr2->nodesIterator(); it->more(); i++ ) {
+      aNodes2[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
+      if ( aNodes2[ i ] == theNode2 )
+        iB2 = i; // node B in tr2
+      else if ( aNodes2[ i ] != theNode1 )
+        i2 = i;  // node 2
+    }
+    
+    // nodes 1 and 2 should not be the same
+    if ( aNodes1[ i1 ] == aNodes2[ i2 ] )
+      return false;
 
-  //MESSAGE( tr1 << tr2 );
+    // tr1: A->2
+    aNodes1[ iA1 ] = aNodes2[ i2 ];
+    // tr2: B->1
+    aNodes2[ iB2 ] = aNodes1[ i1 ];
 
-  GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
-  GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
+    //MESSAGE( tr1 << tr2 );
 
-  //MESSAGE( tr1 << tr2 );
+    GetMeshDS()->ChangeElementNodes( tr1, aNodes1, 3 );
+    GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
 
-  return true;
+    //MESSAGE( tr1 << tr2 );
+    
+    return true;
+  }
 
+  // check case of quadratic faces
+  const SMDS_QuadraticFaceOfNodes* QF1 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr1);
+  if(!QF1) return false;
+  const SMDS_QuadraticFaceOfNodes* QF2 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr2);
+  if(!QF2) return false;
+  return InverseDiag(tr1,tr2);
 }
 
 //=======================================================================
@@ -406,12 +534,16 @@ bool getQuadrangleNodes(const SMDS_MeshNode *    theQuadNodes [],
                         const SMDS_MeshElement * tr1,
                         const SMDS_MeshElement * tr2 )
 {
+  if( tr1->NbNodes() != tr2->NbNodes() )
+    return false;
   // find the 4-th node to insert into tr1
   const SMDS_MeshNode* n4 = 0;
   SMDS_ElemIteratorPtr it = tr2->nodesIterator();
-  while ( !n4 && it->more() )
-  {
+  int i=0;
+  //while ( !n4 && it->more() ) {
+  while ( !n4 && i<3 ) {
     const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+    i++;
     bool isDiag = ( n == theNode1 || n == theNode2 );
     if ( !isDiag )
       n4 = n;
@@ -419,19 +551,19 @@ bool getQuadrangleNodes(const SMDS_MeshNode *    theQuadNodes [],
   // Make an array of nodes to be in a quadrangle
   int iNode = 0, iFirstDiag = -1;
   it = tr1->nodesIterator();
-  while ( it->more() )
-  {
+  i=0;
+  //while ( it->more() ) {
+  while ( i<3 ) {
     const SMDS_MeshNode * n = static_cast<const SMDS_MeshNode*>( it->next() );
+    i++;
     bool isDiag = ( n == theNode1 || n == theNode2 );
-    if ( isDiag )
-    {
+    if ( isDiag ) {
       if ( iFirstDiag < 0 )
         iFirstDiag = iNode;
       else if ( iNode - iFirstDiag == 1 )
         theQuadNodes[ iNode++ ] = n4; // insert the 4-th node between diagonal nodes
     }
-    else if ( n == n4 )
-    {
+    else if ( n == n4 ) {
       return false; // tr1 and tr2 should not have all the same nodes
     }
     theQuadNodes[ iNode++ ] = n;
@@ -459,20 +591,66 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
     return false;
 
   const SMDS_FaceOfNodes* F1 = dynamic_cast<const SMDS_FaceOfNodes*>( tr1 );
-  if (!F1) return false;
+  //if (!F1) return false;
   const SMDS_FaceOfNodes* F2 = dynamic_cast<const SMDS_FaceOfNodes*>( tr2 );
-  if (!F2) return false;
+  //if (!F2) return false;
+  if (F1 && F2) {
 
-  const SMDS_MeshNode* aNodes [ 4 ];
-  if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
-    return false;
+    const SMDS_MeshNode* aNodes [ 4 ];
+    if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
+      return false;
+
+    //MESSAGE( endl << tr1 << tr2 );
+
+    GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
+    GetMeshDS()->RemoveElement( tr2 );
 
-  //MESSAGE( endl << tr1 << tr2 );
+    //MESSAGE( endl << tr1 );
 
-  GetMeshDS()->ChangeElementNodes( tr1, aNodes, 4 );
+    return true;
+  }
+
+  // check case of quadratic faces
+  const SMDS_QuadraticFaceOfNodes* QF1 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr1);
+  if(!QF1) return false;
+  const SMDS_QuadraticFaceOfNodes* QF2 =
+    dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (tr2);
+  if(!QF2) return false;
+
+  //       5
+  //  1 +--+--+ 2  tr1: (1 2 4 5 9 7) or (2 4 1 9 7 5) or (4 1 2 7 5 9)
+  //    |    /|    tr2: (2 3 4 6 8 9) or (3 4 2 8 9 6) or (4 2 3 9 6 8)
+  //    |   / |  
+  //  7 +  +  + 6
+  //    | /9  |
+  //    |/    |
+  //  4 +--+--+ 3  
+  //       8
+  
+  const SMDS_MeshNode* N1 [6];
+  const SMDS_MeshNode* N2 [6];
+  if(!GetNodesFromTwoTria(tr1,tr2,N1,N2))
+    return false;
+  // now we receive following N1 and N2 (using numeration as above image)
+  // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6) 
+  // i.e. first nodes from both arrays determ new diagonal
+
+  const SMDS_MeshNode* aNodes[8];
+  aNodes[0] = N1[0];
+  aNodes[1] = N1[1];
+  aNodes[2] = N2[0];
+  aNodes[3] = N2[1];
+  aNodes[4] = N1[3];
+  aNodes[5] = N2[5];
+  aNodes[6] = N2[3];
+  aNodes[7] = N1[5];
+
+  GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
   GetMeshDS()->RemoveElement( tr2 );
 
-  //MESSAGE( endl << tr1 );
+  // remove middle node (9)
+  GetMeshDS()->RemoveNode( N1[4] );
 
   return true;
 }
@@ -493,16 +671,39 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
   switch ( theElem->GetType() ) {
 
   case SMDSAbs_Edge:
-  case SMDSAbs_Face:
-  {
-    int i = theElem->NbNodes();
-    vector<const SMDS_MeshNode*> aNodes( i );
-    while ( it->more() )
-      aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
-    return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
+  case SMDSAbs_Face: {
+    if(!theElem->IsQuadratic()) {
+      int i = theElem->NbNodes();
+      vector<const SMDS_MeshNode*> aNodes( i );
+      while ( it->more() )
+        aNodes[ --i ]= static_cast<const SMDS_MeshNode*>( it->next() );
+      return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], theElem->NbNodes() );
+    }
+    else {
+      // quadratic elements
+      if(theElem->GetType()==SMDSAbs_Edge) {
+        vector<const SMDS_MeshNode*> aNodes(3);
+        aNodes[1]= static_cast<const SMDS_MeshNode*>( it->next() );
+        aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
+        aNodes[2]= static_cast<const SMDS_MeshNode*>( it->next() );
+        return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], 3 );
+      }
+      else {
+        int nbn = theElem->NbNodes();
+        vector<const SMDS_MeshNode*> aNodes(nbn);
+        aNodes[0]= static_cast<const SMDS_MeshNode*>( it->next() );
+        int i=1;
+        for(; i<nbn/2; i++) {
+          aNodes[nbn/2-i]= static_cast<const SMDS_MeshNode*>( it->next() );
+        }
+        for(i=0; i<nbn/2; i++) {
+          aNodes[nbn-i-1]= static_cast<const SMDS_MeshNode*>( it->next() );
+        }
+        return GetMeshDS()->ChangeElementNodes( theElem, &aNodes[0], nbn );
+      }
+    }
   }
-  case SMDSAbs_Volume:
-  {
+  case SMDSAbs_Volume: {
     if (theElem->IsPoly()) {
       const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
         static_cast<const SMDS_PolyhedralVolumeOfNodes*>( theElem );
@@ -519,16 +720,17 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
       for (int iface = 1; iface <= nbFaces; iface++) {
         int inode, nbFaceNodes = aPolyedre->NbFaceNodes(iface);
         quantities[iface - 1] = nbFaceNodes;
-
+        
         for (inode = nbFaceNodes; inode >= 1; inode--) {
           const SMDS_MeshNode* curNode = aPolyedre->GetFaceNode(iface, inode);
           poly_nodes.push_back(curNode);
         }
       }
-
+      
       return GetMeshDS()->ChangePolyhedronNodes( theElem, poly_nodes, quantities );
 
-    } else {
+    }
+    else {
       SMDS_VolumeTool vTool;
       if ( !vTool.Set( theElem ))
         return false;
@@ -574,54 +776,119 @@ bool SMESH_MeshEditor::QuadToTri (set<const SMDS_MeshElement*> &       theElems,
   SMESHDS_Mesh * aMesh = GetMeshDS();
 
   set< const SMDS_MeshElement * >::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
-    if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 )
+    if ( !elem || elem->GetType() != SMDSAbs_Face )
       continue;
 
-    // retrieve element nodes
-    const SMDS_MeshNode* aNodes [4];
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    int i = 0;
-    while ( itN->more() )
-      aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
-
-    // compare two sets of possible triangles
-    double aBadRate1, aBadRate2; // to what extent a set is bad
-    SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
-    SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
-    aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
+    if(elem->NbNodes()==4) {
 
-    SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
-    SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
-    aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
+      // retrieve element nodes
+      const SMDS_MeshNode* aNodes [4];
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      int i = 0;
+      while ( itN->more() )
+        aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+
+      // compare two sets of possible triangles
+      double aBadRate1, aBadRate2; // to what extent a set is bad
+      SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
+      SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
+      aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
+      
+      SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
+      SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
+      aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
 
-    int aShapeId = FindShape( elem );
-    //MESSAGE( "aBadRate1 = " << aBadRate1 << "; aBadRate2 = " << aBadRate2
+      int aShapeId = FindShape( elem );
+      //MESSAGE( "aBadRate1 = " << aBadRate1 << "; aBadRate2 = " << aBadRate2
       //      << " ShapeID = " << aShapeId << endl << elem );
 
-    if ( aBadRate1 <= aBadRate2 ) {
-      // tr1 + tr2 is better
-      aMesh->ChangeElementNodes( elem, aNodes, 3 );
+      if ( aBadRate1 <= aBadRate2 ) {
+        // tr1 + tr2 is better
+        aMesh->ChangeElementNodes( elem, aNodes, 3 );
+        //MESSAGE( endl << elem );
+
+        elem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+      }
+      else {
+        // tr3 + tr4 is better
+        aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
+        //MESSAGE( endl << elem );
+        
+        elem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+      }
       //MESSAGE( endl << elem );
 
-      elem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+      // put a new triangle on the same shape
+      if ( aShapeId )
+        aMesh->SetMeshElementOnShape( elem, aShapeId );
     }
-    else {
-      // tr3 + tr4 is better
-      aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
-      //MESSAGE( endl << elem );
 
-      elem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+    if( elem->NbNodes()==8 && elem->IsQuadratic() ) {
+      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() );
+      }
+
+      // compare two sets of possible triangles
+      // use for comparing simple triangles (not quadratic)
+      double aBadRate1, aBadRate2; // to what extent a set is bad
+      SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
+      SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
+      aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
+
+      SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
+      SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
+      aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
+
+      int aShapeId = FindShape( elem );
+      
+      // find middle point for (0,1,2,3)
+      // and create node in this point;
+      double x=0., y=0., z=0.;
+      for(i=0; i<4; i++) {
+        x += aNodes[i]->X();
+        y += aNodes[i]->Y();
+        z += aNodes[i]->Z();
+      }
+      const SMDS_MeshNode* newN = aMesh->AddNode(x/4, y/4, z/4);
+
+      if ( aBadRate1 <= aBadRate2 ) {
+        // tr1 + tr2 is better
+        const SMDS_MeshNode* N[6];
+        N[0] = aNodes[0];
+        N[1] = aNodes[1];
+        N[2] = aNodes[2];
+        N[3] = aNodes[4];
+        N[4] = aNodes[5];
+        N[5] = newN;
+        aMesh->ChangeElementNodes( elem, N, 6 );
+        elem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
+                              aNodes[6], aNodes[7], newN );
+      }
+      else {
+        // tr3 + tr4 is better
+        const SMDS_MeshNode* N[6];
+        N[0] = aNodes[1];
+        N[1] = aNodes[2];
+        N[2] = aNodes[3];
+        N[3] = aNodes[5];
+        N[4] = aNodes[6];
+        N[5] = newN;
+        aMesh->ChangeElementNodes( elem, N, 6 );
+        elem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
+                              aNodes[7], aNodes[4], newN );
+      }
+      // put a new triangle on the same shape
+      if ( aShapeId ) {
+        aMesh->SetMeshElementOnShape( elem, aShapeId );
+      }
     }
-    //MESSAGE( endl << elem );
 
-    // put a new triangle on the same shape
-    if ( aShapeId )
-      aMesh->SetMeshElementOnShape( elem, aShapeId );
   }
-
   return true;
 }
 
@@ -635,30 +902,36 @@ int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement*              theQuad,
   if (!theCrit.get())
     return -1;
 
-  if (!theQuad || theQuad->GetType() != SMDSAbs_Face || theQuad->NbNodes() != 4)
+  if (!theQuad || theQuad->GetType() != SMDSAbs_Face )
     return -1;
 
-  // retrieve element nodes
-  const SMDS_MeshNode* aNodes [4];
-  SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
-  int i = 0;
-  while (itN->more())
-    aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+  if( theQuad->NbNodes()==4 ||
+      (theQuad->NbNodes()==8 && theQuad->IsQuadratic()) ) {
 
-  // compare two sets of possible triangles
-  double aBadRate1, aBadRate2; // to what extent a set is bad
-  SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
-  SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
-  aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
+    // retrieve element nodes
+    const SMDS_MeshNode* aNodes [4];
+    SMDS_ElemIteratorPtr itN = theQuad->nodesIterator();
+    int i = 0;
+    //while (itN->more())
+    while (i<4) {
+      aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+    }
+    // compare two sets of possible triangles
+    double aBadRate1, aBadRate2; // to what extent a set is bad
+    SMDS_FaceOfNodes tr1 ( aNodes[0], aNodes[1], aNodes[2] );
+    SMDS_FaceOfNodes tr2 ( aNodes[2], aNodes[3], aNodes[0] );
+    aBadRate1 = getBadRate( &tr1, theCrit ) + getBadRate( &tr2, theCrit );
 
-  SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
-  SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
-  aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
+    SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
+    SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
+    aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
 
-  if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
-    return 1; // diagonal 1-3
+    if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
+      return 1; // diagonal 1-3
 
-  return 2; // diagonal 2-4
+    return 2; // diagonal 2-4
+  }
+  return -1;
 }
 
 //=======================================================================
@@ -693,38 +966,86 @@ bool SMESH_MeshEditor::QuadToTri (std::set<const SMDS_MeshElement*> & theElems,
   SMESHDS_Mesh * aMesh = GetMeshDS();
 
   set< const SMDS_MeshElement * >::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
-    if ( !elem || elem->GetType() != SMDSAbs_Face || elem->NbNodes() != 4 )
+    if ( !elem || elem->GetType() != SMDSAbs_Face )
       continue;
+    bool isquad = elem->NbNodes()==4 || elem->NbNodes()==8;
+    if(!isquad) continue;
 
-    // retrieve element nodes
-    const SMDS_MeshNode* aNodes [4];
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    int i = 0;
-    while ( itN->more() )
-      aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+    if(elem->NbNodes()==4) {
+      // retrieve element nodes
+      const SMDS_MeshNode* aNodes [4];
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      int i = 0;
+      while ( itN->more() )
+        aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
 
-    int aShapeId = FindShape( elem );
-    const SMDS_MeshElement* newElem = 0;
-    if ( the13Diag )
-    {
-      aMesh->ChangeElementNodes( elem, aNodes, 3 );
-      newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
-    }
-    else
-    {
-      aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
-      newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+      int aShapeId = FindShape( elem );
+      const SMDS_MeshElement* newElem = 0;
+      if ( the13Diag ) {
+        aMesh->ChangeElementNodes( elem, aNodes, 3 );
+        newElem = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
+      }
+      else {
+        aMesh->ChangeElementNodes( elem, &aNodes[1], 3 );
+        newElem = aMesh->AddFace( aNodes[3], aNodes[0], aNodes[1] );
+      }
+      // put a new triangle on the same shape and add to the same groups
+      if ( aShapeId )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      AddToSameGroups( newElem, elem, aMesh );
     }
 
-    // put a new triangle on the same shape and add to the same groups
+    if( elem->NbNodes()==8 && elem->IsQuadratic() ) {
+      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() );
+      }
 
-    if ( aShapeId )
-      aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      // find middle point for (0,1,2,3)
+      // and create node in this point;
+      double x=0., y=0., z=0.;
+      for(i=0; i<4; i++) {
+        x += aNodes[i]->X();
+        y += aNodes[i]->Y();
+        z += aNodes[i]->Z();
+      }
+      const SMDS_MeshNode* newN = aMesh->AddNode(x/4, y/4, z/4);
 
-    AddToSameGroups( newElem, elem, aMesh );
+      int aShapeId = FindShape( elem );
+      const SMDS_MeshElement* newElem = 0;
+      if ( the13Diag ) {
+        const SMDS_MeshNode* N[6];
+        N[0] = aNodes[0];
+        N[1] = aNodes[1];
+        N[2] = aNodes[2];
+        N[3] = aNodes[4];
+        N[4] = aNodes[5];
+        N[5] = newN;
+        aMesh->ChangeElementNodes( elem, N, 6 );
+        elem = aMesh->AddFace(aNodes[2], aNodes[3], aNodes[0],
+                              aNodes[6], aNodes[7], newN );
+      }
+      else {
+        const SMDS_MeshNode* N[6];
+        N[0] = aNodes[1];
+        N[1] = aNodes[2];
+        N[2] = aNodes[3];
+        N[3] = aNodes[5];
+        N[4] = aNodes[6];
+        N[5] = newN;
+        aMesh->ChangeElementNodes( elem, N, 6 );
+        elem = aMesh->AddFace(aNodes[3], aNodes[0], aNodes[1],
+                              aNodes[7], aNodes[4], newN );
+      }
+      // put a new triangle on the same shape and add to the same groups
+      if ( aShapeId )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      AddToSameGroups( newElem, elem, aMesh );
+    }
   }
 
   return true;
@@ -747,18 +1068,24 @@ double getAngle(const SMDS_MeshElement * tr1,
   if ( !SMESH::Controls::NumericalFunctor::GetPoints( tr1, P1 ) ||
        !SMESH::Controls::NumericalFunctor::GetPoints( tr2, P2 ))
     return angle;
-  gp_Vec N1 = gp_Vec( P1(2) - P1(1) ) ^ gp_Vec( P1(3) - P1(1) );
+  gp_Vec N1,N2;
+  if(!tr1->IsQuadratic())
+    N1 = gp_Vec( P1(2) - P1(1) ) ^ gp_Vec( P1(3) - P1(1) );
+  else
+    N1 = gp_Vec( P1(3) - P1(1) ) ^ gp_Vec( P1(5) - P1(1) );
   if ( N1.SquareMagnitude() <= gp::Resolution() )
     return angle;
-  gp_Vec N2 = gp_Vec( P2(2) - P2(1) ) ^ gp_Vec( P2(3) - P2(1) );
+  if(!tr2->IsQuadratic())
+    N2 = gp_Vec( P2(2) - P2(1) ) ^ gp_Vec( P2(3) - P2(1) );
+  else
+    N2 = gp_Vec( P2(3) - P2(1) ) ^ gp_Vec( P2(5) - P2(1) );
   if ( N2.SquareMagnitude() <= gp::Resolution() )
     return angle;
 
   // find the first diagonal node n1 in the triangles:
   // take in account a diagonal link orientation
   const SMDS_MeshElement *nFirst[2], *tr[] = { tr1, tr2 };
-  for ( int t = 0; t < 2; t++ )
-  {
+  for ( int t = 0; t < 2; t++ ) {
     SMDS_ElemIteratorPtr it = tr[ t ]->nodesIterator();
     int i = 0, iDiag = -1;
     while ( it->more()) {
@@ -788,7 +1115,6 @@ double getAngle(const SMDS_MeshElement * tr1,
 // class generating a unique ID for a pair of nodes
 // and able to return nodes by that ID
 // =================================================
-
 class LinkID_Gen {
  public:
 
@@ -819,6 +1145,7 @@ class LinkID_Gen {
   long                myMaxID;
 };
 
+
 //=======================================================================
 //function : TriToQuad
 //purpose  : Fuse neighbour triangles into quadrangles.
@@ -837,65 +1164,76 @@ bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> &       theElems,
     return false;
 
   SMESHDS_Mesh * aMesh = GetMeshDS();
-  LinkID_Gen aLinkID_Gen( aMesh );
-
+  //LinkID_Gen aLinkID_Gen( aMesh );
 
   // Prepare data for algo: build
   // 1. map of elements with their linkIDs
   // 2. map of linkIDs with their elements
 
-  map< long, list< const SMDS_MeshElement* > > mapLi_listEl;
-  map< long, list< const SMDS_MeshElement* > >::iterator itLE;
-  map< const SMDS_MeshElement*, set< long > >  mapEl_setLi;
-  map< const SMDS_MeshElement*, set< long > >::iterator itEL;
+  //map< long, list< const SMDS_MeshElement* > > mapLi_listEl;
+  //map< long, list< const SMDS_MeshElement* > >::iterator itLE;
+  //map< const SMDS_MeshElement*, set< long > >  mapEl_setLi;
+  //map< const SMDS_MeshElement*, set< long > >::iterator itEL;
+
+  map< NLink, list< const SMDS_MeshElement* > > mapLi_listEl;
+  map< NLink, list< const SMDS_MeshElement* > >::iterator itLE;
+  map< const SMDS_MeshElement*, set< NLink > >  mapEl_setLi;
+  map< const SMDS_MeshElement*, set< NLink > >::iterator itEL;
 
   set<const SMDS_MeshElement*>::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
-    if ( !elem || elem->NbNodes() != 3 )
-      continue;
+    //if ( !elem || elem->NbNodes() != 3 )
+    //  continue;
+    if(!elem || elem->GetType() != SMDSAbs_Face ) continue;
+    bool IsTria = elem->NbNodes()==3 || (elem->NbNodes()==6 && elem->IsQuadratic());
+    if(!IsTria) continue;
 
     // retrieve element nodes
     const SMDS_MeshNode* aNodes [4];
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
     int i = 0;
-    while ( itN->more() )
+    //while ( itN->more() )
+    while ( i<3 )
       aNodes[ i++ ] = static_cast<const SMDS_MeshNode*>( itN->next() );
     ASSERT( i == 3 );
     aNodes[ 3 ] = aNodes[ 0 ];
 
     // fill maps
-    for ( i = 0; i < 3; i++ )
-    {
-      long linkID = aLinkID_Gen.GetLinkID( aNodes[ i ], aNodes[ i+1 ] );
+    for ( i = 0; i < 3; i++ ) {
+      //long linkID = aLinkID_Gen.GetLinkID( aNodes[ i ], aNodes[ i+1 ] );
+      NLink link(( aNodes[i] < aNodes[i+1] ? aNodes[i] : aNodes[i+1] ),
+                 ( aNodes[i] < aNodes[i+1] ? aNodes[i+1] : aNodes[i] ));
       // check if elements sharing a link can be fused
-      itLE = mapLi_listEl.find( linkID );
-      if ( itLE != mapLi_listEl.end() )
-      {
+      //itLE = mapLi_listEl.find( linkID );
+      itLE = mapLi_listEl.find( link );
+      if ( itLE != mapLi_listEl.end() ) {
         if ((*itLE).second.size() > 1 ) // consider only 2 elems adjacent by a link
           continue;
         const SMDS_MeshElement* elem2 = (*itLE).second.front();
-//         if ( FindShape( elem ) != FindShape( elem2 ))
-//           continue; // do not fuse triangles laying on different shapes
+        //if ( FindShape( elem ) != FindShape( elem2 ))
+        //  continue; // do not fuse triangles laying on different shapes
         if ( getAngle( elem, elem2, aNodes[i], aNodes[i+1] ) > theMaxAngle )
           continue; // avoid making badly shaped quads
         (*itLE).second.push_back( elem );
       }
-      else
-        mapLi_listEl[ linkID ].push_back( elem );
-      mapEl_setLi [ elem ].insert( linkID );
+      else {
+        //mapLi_listEl[ linkID ].push_back( elem );
+        mapLi_listEl[ link ].push_back( elem );
+      }
+      //mapEl_setLi [ elem ].insert( linkID );
+      mapEl_setLi [ elem ].insert( link );
     }
   }
   // Clean the maps from the links shared by a sole element, ie
   // links to which only one element is bound in mapLi_listEl
 
-  for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ )
-  {
+  for ( itLE = mapLi_listEl.begin(); itLE != mapLi_listEl.end(); itLE++ ) {
     int nbElems = (*itLE).second.size();
     if ( nbElems < 2  ) {
       const SMDS_MeshElement* elem = (*itLE).second.front();
-      long link = (*itLE).first;
+      //long link = (*itLE).first;
+      NLink link = (*itLE).first;
       mapEl_setLi[ elem ].erase( link );
       if ( mapEl_setLi[ elem ].empty() )
         mapEl_setLi.erase( elem );
@@ -904,18 +1242,15 @@ bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> &       theElems,
 
   // Algo: fuse triangles into quadrangles
 
-  while ( ! mapEl_setLi.empty() )
-  {
+  while ( ! mapEl_setLi.empty() ) {
     // Look for the start element:
     // the element having the least nb of shared links
 
     const SMDS_MeshElement* startElem = 0;
     int minNbLinks = 4;
-    for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ )
-    {
+    for ( itEL = mapEl_setLi.begin(); itEL != mapEl_setLi.end(); itEL++ ) {
       int nbLinks = (*itEL).second.size();
-      if ( nbLinks < minNbLinks )
-      {
+      if ( nbLinks < minNbLinks ) {
         startElem = (*itEL).first;
         minNbLinks = nbLinks;
         if ( minNbLinks == 1 )
@@ -925,17 +1260,16 @@ bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> &       theElems,
 
     // search elements to fuse starting from startElem or links of elements
     // fused earlyer - startLinks
-    list< long > startLinks;
-    while ( startElem || !startLinks.empty() )
-    {
-      while ( !startElem && !startLinks.empty() )
-      {
+    //list< long > startLinks;
+    list< NLink > startLinks;
+    while ( startElem || !startLinks.empty() ) {
+      while ( !startElem && !startLinks.empty() ) {
         // Get an element to start, by a link
-        long linkId = startLinks.front();
+        //long linkId = startLinks.front();
+        NLink linkId = startLinks.front();
         startLinks.pop_front();
         itLE = mapLi_listEl.find( linkId );
-        if ( itLE != mapLi_listEl.end() )
-        {
+        if ( itLE != mapLi_listEl.end() ) {
           list< const SMDS_MeshElement* > & listElem = (*itLE).second;
           list< const SMDS_MeshElement* >::iterator itE = listElem.begin();
           for ( ; itE != listElem.end() ; itE++ )
@@ -945,69 +1279,83 @@ bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> &       theElems,
         }
       }
 
-      if ( startElem )
-      {
+      if ( startElem ) {
         // Get candidates to be fused
-
         const SMDS_MeshElement *tr1 = startElem, *tr2 = 0, *tr3 = 0;
-        long link12, link13;
+        //long link12, link13;
+        NLink link12, link13;
         startElem = 0;
         ASSERT( mapEl_setLi.find( tr1 ) != mapEl_setLi.end() );
-        set< long >& setLi = mapEl_setLi[ tr1 ];
+        //set< long >& setLi = mapEl_setLi[ tr1 ];
+        set< NLink >& setLi = mapEl_setLi[ tr1 ];
         ASSERT( !setLi.empty() );
-        set< long >::iterator itLi;
-        for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ )
-        {
-          long linkID = (*itLi);
+        //set< long >::iterator itLi;
+        set< NLink >::iterator itLi;
+        for ( itLi = setLi.begin(); itLi != setLi.end(); itLi++ ) {
+          //long linkID = (*itLi);
+          NLink linkID = (*itLi);
           itLE = mapLi_listEl.find( linkID );
           if ( itLE == mapLi_listEl.end() )
             continue;
+
           const SMDS_MeshElement* elem = (*itLE).second.front();
           if ( elem == tr1 )
             elem = (*itLE).second.back();
           mapLi_listEl.erase( itLE );
           if ( mapEl_setLi.find( elem ) == mapEl_setLi.end())
             continue;
-          if ( tr2 )
-          {
+          if ( tr2 ) {
             tr3 = elem;
             link13 = linkID;
           }
-          else
-          {
+          else {
             tr2 = elem;
             link12 = linkID;
           }
 
           // add other links of elem to list of links to re-start from
-          set< long >& links = mapEl_setLi[ elem ];
-          set< long >::iterator it;
-          for ( it = links.begin(); it != links.end(); it++ )
-          {
-            long linkID2 = (*it);
+          //set< long >& links = mapEl_setLi[ elem ];
+          //set< long >::iterator it;
+          set< NLink >& links = mapEl_setLi[ elem ];
+          set< NLink >::iterator it;
+          for ( it = links.begin(); it != links.end(); it++ ) {
+            //long linkID2 = (*it);
+            NLink linkID2 = (*it);
             if ( linkID2 != linkID )
               startLinks.push_back( linkID2 );
           }
         }
 
         // Get nodes of possible quadrangles
-
         const SMDS_MeshNode *n12 [4], *n13 [4];
         bool Ok12 = false, Ok13 = false;
+        //const SMDS_MeshNode *linkNode1, *linkNode2;
         const SMDS_MeshNode *linkNode1, *linkNode2;
-        if ( tr2 &&
-             aLinkID_Gen.GetNodes( link12, linkNode1, linkNode2 ) &&
-             getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
-          Ok12 = true;
-        if ( tr3 &&
-             aLinkID_Gen.GetNodes( link13, linkNode1, linkNode2 ) &&
-             getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
-          Ok13 = true;
+        if(tr2) {
+          //const SMDS_MeshNode *linkNode1 = link12.first;
+          //const SMDS_MeshNode *linkNode2 = link12.second;
+          linkNode1 = link12.first;
+          linkNode2 = link12.second;
+          //if ( tr2 &&
+          //     aLinkID_Gen.GetNodes( link12, linkNode1, linkNode2 ) &&
+          //     getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
+          //  Ok12 = true;
+          if ( tr2 && getQuadrangleNodes( n12, linkNode1, linkNode2, tr1, tr2 ))
+            Ok12 = true;
+        }
+        if(tr3) {
+          linkNode1 = link13.first;
+          linkNode2 = link13.second;
+          //if ( tr3 &&
+          //     aLinkID_Gen.GetNodes( link13, linkNode1, linkNode2 ) &&
+          //     getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
+          //  Ok13 = true;
+          if ( tr3 && getQuadrangleNodes( n13, linkNode1, linkNode2, tr1, tr3 ))
+            Ok13 = true;
+        }
 
         // Choose a pair to fuse
-
-        if ( Ok12 && Ok13 )
-        {
+        if ( Ok12 && Ok13 ) {
           SMDS_FaceOfNodes quad12 ( n12[ 0 ], n12[ 1 ], n12[ 2 ], n12[ 3 ] );
           SMDS_FaceOfNodes quad13 ( n13[ 0 ], n13[ 1 ], n13[ 2 ], n13[ 3 ] );
           double aBadRate12 = getBadRate( &quad12, theCrit );
@@ -1018,24 +1366,66 @@ bool SMESH_MeshEditor::TriToQuad (set<const SMDS_MeshElement*> &       theElems,
             Ok13 = false;
         }
 
-
         // Make quadrangles
         // and remove fused elems and removed links from the maps
-
         mapEl_setLi.erase( tr1 );
-        if ( Ok12 )
-        {
+        if ( Ok12 ) {
           mapEl_setLi.erase( tr2 );
           mapLi_listEl.erase( link12 );
-          aMesh->ChangeElementNodes( tr1, n12, 4 );
-          aMesh->RemoveElement( tr2 );
+          if(tr1->NbNodes()==3) {
+            aMesh->ChangeElementNodes( tr1, n12, 4 );
+            aMesh->RemoveElement( tr2 );
+          }
+          else {
+            const SMDS_MeshNode* N1 [6];
+            const SMDS_MeshNode* N2 [6];
+            GetNodesFromTwoTria(tr1,tr2,N1,N2);
+            // now we receive following N1 and N2 (using numeration as above image)
+            // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6) 
+            // i.e. first nodes from both arrays determ new diagonal
+            const SMDS_MeshNode* aNodes[8];
+            aNodes[0] = N1[0];
+            aNodes[1] = N1[1];
+            aNodes[2] = N2[0];
+            aNodes[3] = N2[1];
+            aNodes[4] = N1[3];
+            aNodes[5] = N2[5];
+            aNodes[6] = N2[3];
+            aNodes[7] = N1[5];
+            GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
+            GetMeshDS()->RemoveElement( tr2 );
+            // remove middle node (9)
+            GetMeshDS()->RemoveNode( N1[4] );
+          }
         }
-        else if ( Ok13 )
-        {
+        else if ( Ok13 ) {
           mapEl_setLi.erase( tr3 );
           mapLi_listEl.erase( link13 );
-          aMesh->ChangeElementNodes( tr1, n13, 4 );
-          aMesh->RemoveElement( tr3 );
+          if(tr1->NbNodes()==3) {
+            aMesh->ChangeElementNodes( tr1, n13, 4 );
+            aMesh->RemoveElement( tr3 );
+          }
+          else {
+            const SMDS_MeshNode* N1 [6];
+            const SMDS_MeshNode* N2 [6];
+            GetNodesFromTwoTria(tr1,tr3,N1,N2);
+            // now we receive following N1 and N2 (using numeration as above image)
+            // tria1 : (1 2 4 5 9 7)  and  tria2 : (3 4 2 8 9 6) 
+            // i.e. first nodes from both arrays determ new diagonal
+            const SMDS_MeshNode* aNodes[8];
+            aNodes[0] = N1[0];
+            aNodes[1] = N1[1];
+            aNodes[2] = N2[0];
+            aNodes[3] = N2[1];
+            aNodes[4] = N1[3];
+            aNodes[5] = N2[5];
+            aNodes[6] = N2[3];
+            aNodes[7] = N1[5];
+            GetMeshDS()->ChangeElementNodes( tr1, aNodes, 8 );
+            GetMeshDS()->RemoveElement( tr3 );
+            // remove middle node (9)
+            GetMeshDS()->RemoveNode( N1[4] );
+          }
         }
 
         // Next element to fuse: the rejected one
@@ -1352,13 +1742,25 @@ void laplacianSmooth(const SMDS_MeshNode*                 theNode,
     // put all nodes in array
     int nbNodes = 0, iNode = 0;
     vector< const SMDS_MeshNode*> aNodes( elem->NbNodes() );
-    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() )
-    {
-      aNodes[ nbNodes ] = static_cast<const SMDS_MeshNode*>( itN->next() );
-      if ( aNodes[ nbNodes ] == theNode )
-        iNode = nbNodes; // index of theNode within aNodes
-      nbNodes++;
+    if(!elem->IsQuadratic()) {
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      while ( itN->more() ) {
+        aNodes[ nbNodes ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+        if ( aNodes[ nbNodes ] == theNode )
+          iNode = nbNodes; // index of theNode within aNodes
+        nbNodes++;
+      }
+    }
+    else {
+      int nbn = elem->NbNodes()/2;
+      aNodes.resize(nbn);
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      while ( nbNodes<nbn ) {
+        aNodes[ nbNodes ] = static_cast<const SMDS_MeshNode*>( itN->next() );
+        if ( aNodes[ nbNodes ] == theNode )
+          iNode = nbNodes; // index of theNode within aNodes
+        nbNodes++;
+      }
     }
     // add linked nodes
     int iAfter = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
@@ -1435,9 +1837,13 @@ void centroidalSmooth(const SMDS_MeshNode*                 theNode,
     gp_XYZ elemCenter(0.,0.,0.);
     SMESH::Controls::TSequenceOfXYZ aNodePoints;
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() )
-    {
+    int nn = elem->NbNodes();
+    if(elem->IsQuadratic()) nn = nn/2;
+    int i=0;
+    //while ( itN->more() ) {
+    while ( i<nn ) {
       const SMDS_MeshNode* aNode = static_cast<const SMDS_MeshNode*>( itN->next() );
+      i++;
       gp_XYZ aP( aNode->X(), aNode->Y(), aNode->Z() );
       aNodePoints.push_back( aP );
       if ( !theSurface.IsNull() ) { // smooth in 2D
@@ -1509,6 +1915,8 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
   if ( theTgtAspectRatio < 1.0 )
     theTgtAspectRatio = 1.0;
 
+  double disttol = 1.e-16;
+
   SMESH::Controls::AspectRatio aQualityFunc;
 
   SMESHDS_Mesh* aMesh = GetMeshDS();
@@ -1540,9 +1948,10 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
   // smooth elements on each TopoDS_Face separately
   // ===============================================
 
+  set<const SMDS_MeshElement*> QuadElems;
+
   set< int >::reverse_iterator fId = faceIdSet.rbegin(); // treate 0 fId at the end
-  for ( ; fId != faceIdSet.rend(); ++fId )
-  {
+  for ( ; fId != faceIdSet.rend(); ++fId ) {
     // get face surface and submesh
     Handle(Geom_Surface) surface;
     SMESHDS_SubMesh* faceSubMesh = 0;
@@ -1583,8 +1992,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
     int nbElemOnFace = 0;
     itElem = theElems.begin();
      // loop on not yet smoothed elements: look for elems on a face
-    while ( itElem != theElems.end() )
-    {
+    while ( itElem != theElems.end() ) {
       if ( faceSubMesh && nbElemOnFace == faceSubMesh->NbElements() )
         break; // all elements found
 
@@ -1595,6 +2003,9 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
         continue;
       }
       elemsOnFace.push_back( elem );
+      if(elem->IsQuadratic()) {
+        QuadElems.insert(elem);
+      }
       theElems.erase( itElem++ );
       nbElemOnFace++;
 
@@ -1602,7 +2013,13 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
       const SMDS_MeshNode* node;
       SMDS_TypeOfPosition posType;
       SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-      while ( itN->more() ) {
+      int nbn =  elem->NbNodes();
+      if(elem->IsQuadratic())
+        nbn = nbn/2;
+      int nn = 0;
+      //while ( itN->more() ) {
+      while ( nn<nbn ) {
+        nn++;
         node = static_cast<const SMDS_MeshNode*>( itN->next() );
         const SMDS_PositionPtr& pos = node->GetPosition();
         posType = pos.get() ? pos->GetTypeOfPosition() : SMDS_TOP_3DSPACE;
@@ -1657,8 +2074,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
       }
       // check UV on face
       list< const SMDS_MeshNode* >::iterator n = uvCheckNodes.begin();
-      for ( ; n != uvCheckNodes.end(); ++n )
-      {
+      for ( ; n != uvCheckNodes.end(); ++n ) {
         node = *n;
         gp_XY uv( 0, 0 );
         const SMDS_PositionPtr& pos = node->GetPosition();
@@ -1725,21 +2141,31 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
 
     // fix nodes on mesh boundary
 
-    if ( checkBoundaryNodes )
-    {
+    if ( checkBoundaryNodes ) {
       typedef pair<const SMDS_MeshNode*, const SMDS_MeshNode*> TLink;
       map< TLink, int > linkNbMap; // how many times a link encounters in elemsOnFace
       map< TLink, int >::iterator link_nb;
       // put all elements links to linkNbMap
       list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
-      for ( ; elemIt != elemsOnFace.end(); ++elemIt )
-      {
+      for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
+        const SMDS_MeshElement* elem = (*elemIt);
         // put elem nodes in array
         vector< const SMDS_MeshNode* > nodes;
-        nodes.reserve( (*elemIt)->NbNodes() + 1 );
-        SMDS_ElemIteratorPtr itN = (*elemIt)->nodesIterator();
-        while ( itN->more() )
-          nodes.push_back( static_cast<const SMDS_MeshNode*>( itN->next() ));
+        if(!elem->IsQuadratic()) {
+          nodes.reserve( elem->NbNodes() + 1 );
+          SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+          while ( itN->more() )
+            nodes.push_back( static_cast<const SMDS_MeshNode*>( itN->next() ));
+        }
+        else {
+          nodes.reserve( elem->NbNodes()/2 + 1 );
+          SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+          int nbn = 0;
+          while ( nbn<elem->NbNodes()/2 ) {
+            nbn++;
+            nodes.push_back( static_cast<const SMDS_MeshNode*>( itN->next() ));
+          }
+        }
         nodes.push_back( nodes.front() );
         // loop on elem links: insert them in linkNbMap
         for ( int iN = 1; iN < nodes.size(); ++iN ) {
@@ -1771,11 +2197,9 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
     // -----------------------------------------------------
 
     set<const SMDS_MeshNode*> nodesNearSeam; // to smooth using uvMap2
-    if ( !surface.IsNull() )
-    {
+    if ( !surface.IsNull() ) {
       TopExp_Explorer eExp( face, TopAbs_EDGE );
-      for ( ; eExp.More(); eExp.Next() )
-      {
+      for ( ; eExp.More(); eExp.Next() ) {
         TopoDS_Edge edge = TopoDS::Edge( eExp.Current() );
         if ( !BRep_Tool::IsClosed( edge, face ))
           continue;
@@ -1812,8 +2236,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
         }
         // loop on nodes on seam
         list< const SMDS_MeshNode* >::iterator noSeIt = seamNodes.begin();
-        for ( ; noSeIt != seamNodes.end(); ++noSeIt )
-        {
+        for ( ; noSeIt != seamNodes.end(); ++noSeIt ) {
           const SMDS_MeshNode* nSeam = *noSeIt;
           map< const SMDS_MeshNode*, gp_XY* >::iterator n_uv = uvMap.find( nSeam );
           if ( n_uv == uvMap.end() )
@@ -1829,8 +2252,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
 
           // collect movable nodes linked to ones on seam in nodesNearSeam
           SMDS_ElemIteratorPtr eIt = nSeam->GetInverseElementIterator();
-          while ( eIt->more() )
-          {
+          while ( eIt->more() ) {
             const SMDS_MeshElement* e = eIt->next();
             if ( e->GetType() != SMDSAbs_Face )
               continue;
@@ -1858,8 +2280,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
             }
             // for centroidalSmooth all element nodes must
             // be on one side of a seam
-            if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 )
-            {
+            if ( theSmoothMethod == CENTROIDAL && nbUseMap1 && nbUseMap2 ) {
               SMDS_ElemIteratorPtr nIt = e->nodesIterator();
               while ( nIt->more() ) {
                 const SMDS_MeshNode* n =
@@ -1884,12 +2305,10 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
     int it = -1;
     double maxRatio = -1., maxDisplacement = -1.;
     set<const SMDS_MeshNode*>::iterator nodeToMove;
-    for ( it = 0; it < theNbIterations; it++ )
-    {
+    for ( it = 0; it < theNbIterations; it++ ) {
       maxDisplacement = 0.;
       nodeToMove = setMovableNodes.begin();
-      for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ )
-      {
+      for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
         const SMDS_MeshNode* node = (*nodeToMove);
         gp_XYZ aPrevPos ( node->X(), node->Y(), node->Z() );
 
@@ -1907,7 +2326,8 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
           maxDisplacement = aDispl;
       }
       // no node movement => exit
-      if ( maxDisplacement < 1.e-16 ) {
+      //if ( maxDisplacement < 1.e-16 ) {
+      if ( maxDisplacement < disttol ) {
         MESSAGE("-- no node movement --");
         break;
       }
@@ -1915,8 +2335,7 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
       // check elements quality
       maxRatio  = 0;
       list< const SMDS_MeshElement* >::iterator elemIt = elemsOnFace.begin();
-      for ( ; elemIt != elemsOnFace.end(); ++elemIt )
-      {
+      for ( ; elemIt != elemsOnFace.end(); ++elemIt ) {
         const SMDS_MeshElement* elem = (*elemIt);
         if ( !elem || elem->GetType() != SMDSAbs_Face )
           continue;
@@ -1945,10 +2364,8 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
     // new nodes positions are computed,
     // record movement in DS and set new UV
     // ---------------------------------------
-
     nodeToMove = setMovableNodes.begin();
-    for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ )
-    {
+    for ( ; nodeToMove != setMovableNodes.end(); nodeToMove++ ) {
       SMDS_MeshNode* node = const_cast< SMDS_MeshNode* > (*nodeToMove);
       aMesh->MoveNode( node, node->X(), node->Y(), node->Z() );
       map< const SMDS_MeshNode*, gp_XY* >::iterator node_uv = uvMap.find( node );
@@ -1960,6 +2377,38 @@ void SMESH_MeshEditor::Smooth (set<const SMDS_MeshElement*> & theElems,
     }
 
   } // loop on face ids
+
+  set< const SMDS_MeshElement* >::iterator itq;
+  for ( itq = QuadElems.begin(); itq != QuadElems.end(); itq++ ) {
+    const SMDS_QuadraticFaceOfNodes* QF =
+      dynamic_cast<const SMDS_QuadraticFaceOfNodes*> (*itq);
+    if(QF) {
+      vector<const SMDS_MeshNode*> Ns(QF->NbNodes()+1);
+      SMDS_NodeIteratorPtr anIter = QF->interlacedNodesIterator();
+      int nn = 0;
+      while( anIter->more() ) {
+        Ns[nn++] = anIter->next();
+        //Ns.push_back(anIter->next());
+      }
+      Ns[nn] = Ns[0];
+      //Ns.push_back(Ns[0]);
+      int i=0;
+      for(; i<QF->NbNodes(); i=i+2) {
+        double x = (Ns[i]->X() + Ns[i+2]->X())/2;
+        double y = (Ns[i]->Y() + Ns[i+2]->Y())/2;
+        double z = (Ns[i]->Z() + Ns[i+2]->Z())/2;
+        if( fabs( Ns[i+1]->X() - x ) > disttol ||
+           fabs( Ns[i+1]->Y() - y ) > disttol ||
+           fabs( Ns[i+1]->Z() - z ) > disttol ) {
+          // we have to move i+1 node
+          const_cast<SMDS_MeshNode*>(Ns[i+1])->setXYZ(x,y,z);
+          aMesh->MoveNode( Ns[i+1], x, y, z );
+        }
+      }
+    }
+  }
+  QuadElems.clear();
+
 }
 
 //=======================================================================
@@ -2000,38 +2449,57 @@ static bool isReverse(const SMDS_MeshNode* prevNodes[],
 static void sweepElement(SMESHDS_Mesh*                         aMesh,
                          const SMDS_MeshElement*               elem,
                          const vector<TNodeOfNodeListMapItr> & newNodesItVec,
-                         list<const SMDS_MeshElement*>&        newElems)
+                         list<const SMDS_MeshElement*>&        newElems,
+                         const int nbSteps)
 {
   // Loop on elem nodes:
   // find new nodes and detect same nodes indices
   int nbNodes = elem->NbNodes();
   list<const SMDS_MeshNode*>::const_iterator itNN[ nbNodes ];
-  const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ];
+  const SMDS_MeshNode* prevNod[ nbNodes ], *nextNod[ nbNodes ], *midlNod[ nbNodes ];
   int iNode, nbSame = 0, iNotSameNode = 0, iSameNode = 0;
+  vector<int> sames(nbNodes);
 
-  for ( iNode = 0; iNode < nbNodes; iNode++ )
-  {
+  bool issimple[nbNodes];
+
+  for ( iNode = 0; iNode < nbNodes; iNode++ ) {
     TNodeOfNodeListMapItr nnIt = newNodesItVec[ iNode ];
     const SMDS_MeshNode*                 node         = nnIt->first;
     const list< const SMDS_MeshNode* > & listNewNodes = nnIt->second;
     if ( listNewNodes.empty() )
       return;
 
+    if(listNewNodes.size()==nbSteps) {
+      issimple[iNode] = true;
+    }
+    else {
+      issimple[iNode] = false;
+    }
+
     itNN[ iNode ] = listNewNodes.begin();
     prevNod[ iNode ] = node;
     nextNod[ iNode ] = listNewNodes.front();
+//cout<<"iNode="<<iNode<<endl;
+//cout<<" prevNod[iNode]="<< prevNod[iNode]<<" nextNod[iNode]="<< nextNod[iNode]<<endl;
     if ( prevNod[ iNode ] != nextNod [ iNode ])
       iNotSameNode = iNode;
     else {
       iSameNode = iNode;
-      nbSame++;
+      //nbSame++;
+      sames[nbSame++] = iNode;
     }
   }
+//cout<<"1 nbSame="<<nbSame<<endl;
   if ( nbSame == nbNodes || nbSame > 2) {
     MESSAGE( " 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;
   if ( nbSame > 0 ) {
     iBeforeSame = ( iSameNode == 0 ? nbNodes - 1 : iSameNode - 1 );
@@ -2039,6 +2507,12 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
     iOpposSame  = ( iSameNode - 2 < 0  ? iSameNode + 2 : iSameNode - 2 );
   }
 
+//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 )) {
@@ -2053,82 +2527,195 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
   }
 
   // make new elements
-  int iStep, nbSteps = newNodesItVec[ 0 ]->second.size();
-  for (iStep = 0; iStep < nbSteps; iStep++ )
-  {
+  int iStep;//, nbSteps = newNodesItVec[ 0 ]->second.size();
+  for (iStep = 0; iStep < nbSteps; iStep++ ) {
     // get next nodes
     for ( iNode = 0; iNode < nbNodes; iNode++ ) {
-      nextNod[ iNode ] = *itNN[ iNode ];
-      itNN[ 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() ||
+           elem->IsQuadratic() && elem->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 ]++;
+        }
+      }
     }
     SMDS_MeshElement* aNewElem = 0;
-    switch ( nbNodes )
-    {
-    case 0:
-      return;
-    case 1: { // NODE
-      if ( nbSame == 0 )
-        aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
-      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 ] );
-      break;
-    }
-    case 3: { // TRIANGLE
-
-      if ( nbSame == 0 )       // --- pentahedron
-        aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
-                                     nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
+    if(!elem->IsPoly()) {
+      switch ( nbNodes ) {
+      case 0:
+        return;
+      case 1: { // NODE
+        if ( nbSame == 0 ) {
+          if(issimple[0])
+            aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ] );
+          else
+            aNewElem = aMesh->AddEdge( prevNod[ 0 ], nextNod[ 0 ], midlNod[ 0 ] );
+        }
+        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 ] );
+        break;
+      }
 
-      else if ( nbSame == 1 )  // --- pyramid
-        aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
-                                     nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
-                                     nextNod[ iSameNode ]);
+      case 3: { // TRIANGLE or quadratic edge
+        if(elem->GetType() == SMDSAbs_Face) { // TRIANGLE
 
-      else // 2 same nodes:      --- tetrahedron
-        aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
-                                     nextNod[ iNotSameNode ]);
-      break;
-    }
-    case 4: { // QUADRANGLE
+          if ( nbSame == 0 )       // --- pentahedron
+            aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
+                                         nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ] );
 
-      if ( nbSame == 0 )       // --- hexahedron
-        aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
-                                     nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);
+          else if ( nbSame == 1 )  // --- pyramid
+            aNewElem = aMesh->AddVolume (prevNod[ iBeforeSame ],  prevNod[ iAfterSame ],
+                                         nextNod[ iAfterSame ], nextNod[ iBeforeSame ],
+                                         nextNod[ iSameNode ]);
 
-      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 ],
-                                     nextNod[ iOpposSame ],  nextNod[ iBeforeSame ] );
-      }
-      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 ],
-                                       prevNod[ iAfterSame ],  nextNod[ iAfterSame ]);
-        else
-          // iAfterSame is same too
-          aNewElem = aMesh->AddVolume (prevNod[ iSameNode ], prevNod[ iBeforeSame ],
-                                       nextNod[ iBeforeSame ], prevNod[ iAfterSame ],
-                                       prevNod[ iOpposSame ],  nextNod[ iOpposSame ]);
+          else // 2 same nodes:      --- tetrahedron
+            aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ],
+                                         nextNod[ iNotSameNode ]);
+        }
+        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
+            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
+            return;
+        }
+        break;
+      }
+      case 4: { // QUADRANGLE
+
+        if ( nbSame == 0 )       // --- hexahedron
+          aNewElem = aMesh->AddVolume (prevNod[ i0 ], prevNod[ 1 ], prevNod[ i2 ], prevNod[ 3 ],
+                                       nextNod[ i0 ], nextNod[ 1 ], nextNod[ i2 ], nextNod[ 3 ]);
+        
+        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 ],
+                                       nextNod[ iOpposSame ],  nextNod[ iBeforeSame ] );
+        }
+        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 ],
+                                         prevNod[ iAfterSame ],  nextNod[ iAfterSame ]);
+          else
+            // iAfterSame is same too
+            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
+        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]);
+        }
+        break;
+      }
+      case 8: { // quadratic quadrangle
+        // 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]);
+        }
+        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);
+        break;
+      }
       }
-      break;
     }
-    default: {
+
+    if(!aNewElem) {
       // realized for extrusion only
       vector<const SMDS_MeshNode*> polyedre_nodes (nbNodes*2 + 4*nbNodes);
       vector<int> quantities (nbNodes + 2);
@@ -2153,9 +2740,10 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
       }
       aNewElem = aMesh->AddPolyhedralVolume (polyedre_nodes, quantities);
     }
-    }
-    if ( aNewElem )
+
+    if ( aNewElem ) {
       newElems.push_back( aNewElem );
+    }
 
     // set new prev nodes
     for ( iNode = 0; iNode < nbNodes; iNode++ )
@@ -2173,26 +2761,33 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
                        TNodeOfNodeListMap &          mapNewNodes,
                        TElemOfElemListMap &          newElemsMap,
                        TElemOfVecOfNnlmiMap &        elemNewNodesMap,
-                       set<const SMDS_MeshElement*>& elemSet)
+                       set<const SMDS_MeshElement*>& elemSet,
+                       const int nbSteps)
 {
   ASSERT( newElemsMap.size() == elemNewNodesMap.size() );
 
   // 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();
     int nbInitElems = 0;
-    while ( eIt->more() && nbInitElems < 2 )
-      if ( elemSet.find( eIt->next() ) != elemSet.end() )
+    const SMDS_MeshElement* el;
+    while ( eIt->more() && nbInitElems < 2 ) {
+      el = eIt->next();
+      //if ( elemSet.find( eIt->next() ) != elemSet.end() )
+      if ( elemSet.find(el) != elemSet.end() )
         nbInitElems++;
+    }
     if ( nbInitElems < 2 ) {
-      vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
-      list<const SMDS_MeshElement*> newEdges;
-      sweepElement( aMesh, node, newNodesItVec, newEdges );
+      bool NotCreateEdge = el->IsQuadratic() && el->IsMediumNode(node);
+      if(!NotCreateEdge) {
+        vector<TNodeOfNodeListMapItr> newNodesItVec( 1, nList );
+        list<const SMDS_MeshElement*> newEdges;
+        sweepElement( aMesh, node, newNodesItVec, newEdges, nbSteps );
+      }
     }
   }
 
@@ -2201,16 +2796,22 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
 
   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 ( elem->GetType() == SMDSAbs_Edge )
-    {
-      // create a ceiling edge
-      aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
-                     vecNewNodes[ 1 ]->second.back() );
+    if ( elem->GetType() == SMDSAbs_Edge ) {
+      if(!elem->IsQuadratic()) {
+        // create a ceiling edge
+        aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+                       vecNewNodes[ 1 ]->second.back() );
+      }
+      else {
+        // create a ceiling edge
+        aMesh->AddEdge(vecNewNodes[ 0 ]->second.back(),
+                       vecNewNodes[ 1 ]->second.back(),
+                       vecNewNodes[ 2 ]->second.back());
+      }
     }
     if ( elem->GetType() != SMDSAbs_Face )
       continue;
@@ -2220,43 +2821,72 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
     set<const SMDS_MeshElement*> avoidSet;
     avoidSet.insert( elem );
 
-    // loop on a face nodes
     set<const SMDS_MeshNode*> aFaceLastNodes;
     int iNode, nbNodes = vecNewNodes.size();
-    for ( iNode = 0; iNode < nbNodes; iNode++ )
-    {
-      aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
-      // look for free links of a face
-      int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
-      const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
-      const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
-      // check if a link is free
-      if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet ))
-      {
-        hasFreeLinks = true;
-        // make an edge and a ceiling for a new edge
-        if ( !aMesh->FindEdge( n1, n2 ))
-          aMesh->AddEdge( n1, n2 );
-        n1 = vecNewNodes[ iNode ]->second.back();
-        n2 = vecNewNodes[ iNext ]->second.back();
-        if ( !aMesh->FindEdge( n1, n2 ))
-          aMesh->AddEdge( n1, n2 );
+    if(!elem->IsQuadratic()) {
+      // loop on a face nodes
+      for ( iNode = 0; iNode < nbNodes; iNode++ ) {
+        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
+        // look for free links of a face
+        int iNext = ( iNode + 1 == nbNodes ) ? 0 : iNode + 1;
+        const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
+        const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
+        // check if a link is free
+        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, n2, elemSet, avoidSet )) {
+          hasFreeLinks = true;
+          // make an edge and a ceiling for a new edge
+          if ( !aMesh->FindEdge( n1, n2 )) {
+            aMesh->AddEdge( n1, n2 );
+          }
+          n1 = vecNewNodes[ iNode ]->second.back();
+          n2 = vecNewNodes[ iNext ]->second.back();
+          if ( !aMesh->FindEdge( n1, n2 )) {
+            aMesh->AddEdge( n1, n2 );
+          }
+        }
+      }
+    }
+    else { // elem is quadratic face
+      int nbn = nbNodes/2;
+      for ( iNode = 0; iNode < nbn; iNode++ ) {
+        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
+        int iNext = ( iNode + 1 == nbn ) ? 0 : iNode + 1;
+        const SMDS_MeshNode* n1 = vecNewNodes[ iNode ]->first;
+        const SMDS_MeshNode* n2 = vecNewNodes[ iNext ]->first;
+        // check if a link is free
+        if ( ! SMESH_MeshEditor::FindFaceInSet ( n1, 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 )) {
+            aMesh->AddEdge( n1, n2, n3 );
+          }
+          n1 = vecNewNodes[ iNode ]->second.back();
+          n2 = vecNewNodes[ iNext ]->second.back();
+          n3 = vecNewNodes[ iNode+nbn ]->second.back();
+          if ( !aMesh->FindEdge( n1, n2, n3 )) {
+            aMesh->AddEdge( n1, n2, n3 );
+          }
+        }
+      }
+      for ( iNode = nbn; iNode < 2*nbn; iNode++ ) {
+        aFaceLastNodes.insert( vecNewNodes[ iNode ]->second.back() );
       }
     }
+
     // sweep free links into faces
 
-    if ( hasFreeLinks )
-    {
+    if ( hasFreeLinks )  {
       list<const SMDS_MeshElement*> & newVolumes = itElem->second;
-      int iStep, nbSteps = vecNewNodes[0]->second.size();
+      int iStep; //, nbSteps = vecNewNodes[0]->second.size();
       int iVol, volNb, nbVolumesByStep = newVolumes.size() / nbSteps;
 
       set<const SMDS_MeshNode*> initNodeSet, faceNodeSet;
       for ( iNode = 0; iNode < nbNodes; iNode++ )
         initNodeSet.insert( vecNewNodes[ iNode ]->first );
 
-      for ( volNb = 0; volNb < nbVolumesByStep; volNb++ )
-      {
+      for ( volNb = 0; volNb < nbVolumesByStep; volNb++ ) {
         list<const SMDS_MeshElement*>::iterator v = newVolumes.begin();
         iVol = 0;
         while ( iVol++ < volNb ) v++;
@@ -2264,36 +2894,50 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
         list< int > fInd;
         SMDS_VolumeTool vTool( *v );
         int iF, nbF = vTool.NbFaces();
-        for ( iF = 0; iF < nbF; iF ++ )
+        for ( iF = 0; iF < nbF; iF ++ ) {
           if (vTool.IsFreeFace( iF ) &&
               vTool.GetFaceNodes( iF, faceNodeSet ) &&
               initNodeSet != faceNodeSet) // except an initial face
             fInd.push_back( iF );
+        }
         if ( fInd.empty() )
           continue;
 
         // create faces for all steps
-        for ( iStep = 0; iStep < nbSteps; iStep++ )
-        {
+        for ( iStep = 0; iStep < nbSteps; iStep++ )  {
           vTool.Set( *v );
           vTool.SetExternalNormal();
           list< int >::iterator ind = fInd.begin();
-          for ( ; ind != fInd.end(); ind++ )
-          {
+          for ( ; ind != fInd.end(); ind++ ) {
             const SMDS_MeshNode** nodes = vTool.GetFaceNodes( *ind );
-            switch ( vTool.NbFaceNodes( *ind ) ) {
+            int nbn = vTool.NbFaceNodes( *ind );
+            //switch ( vTool.NbFaceNodes( *ind ) ) {
+            switch ( nbn ) {
             case 3:
               aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ); break;
             case 4:
               aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ], nodes[ 3 ] ); break;
             default:
               {
-                int nbPolygonNodes = vTool.NbFaceNodes( *ind );
-                vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
-                for (int inode = 0; inode < nbPolygonNodes; inode++) {
-                  polygon_nodes[inode] = nodes[inode];
+                if( (*v)->IsQuadratic() ) {
+                  if(nbn==6) {
+                    aMesh->AddFace(nodes[0], nodes[2], nodes[4],
+                                   nodes[1], nodes[3], nodes[5]); break;
+                  }
+                  else {
+                      aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                                     nodes[1], nodes[3], nodes[5], nodes[7]);
+                      break;
+                  }
+                }
+                else {
+                  int nbPolygonNodes = vTool.NbFaceNodes( *ind );
+                  vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
+                  for (int inode = 0; inode < nbPolygonNodes; inode++) {
+                    polygon_nodes[inode] = nodes[inode];
+                  }
+                  aMesh->AddPolygonalFace(polygon_nodes);
                 }
-                aMesh->AddPolygonalFace(polygon_nodes);
                 break;
               }
             }
@@ -2308,12 +2952,13 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
     // make a ceiling face with a normal external to a volume
 
     SMDS_VolumeTool lastVol( itElem->second.back() );
+
     int iF = lastVol.GetFaceIndex( aFaceLastNodes );
-    if ( iF >= 0 )
-    {
+    if ( iF >= 0 ) {
       lastVol.SetExternalNormal();
       const SMDS_MeshNode** nodes = lastVol.GetFaceNodes( iF );
-      switch ( lastVol.NbFaceNodes( iF ) ) {
+      int nbn = lastVol.NbFaceNodes( iF );
+      switch ( nbn ) {
       case 3:
         if (!hasFreeLinks ||
             !aMesh->FindFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ]))
@@ -2326,18 +2971,36 @@ static void makeWalls (SMESHDS_Mesh*                 aMesh,
         break;
       default:
         {
-          int nbPolygonNodes = lastVol.NbFaceNodes( iF );
-          vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
-          for (int inode = 0; inode < nbPolygonNodes; inode++) {
-            polygon_nodes[inode] = nodes[inode];
+          if(itElem->second.back()->IsQuadratic()) {
+            if(nbn==6) {
+              if (!hasFreeLinks ||
+                  !aMesh->FindFace(nodes[0], nodes[2], nodes[4],
+                                   nodes[1], nodes[3], nodes[5]) ) {
+                aMesh->AddFace(nodes[0], nodes[2], nodes[4],
+                               nodes[1], nodes[3], nodes[5]); break;
+              }
+            }
+            else { // nbn==8
+              if (!hasFreeLinks ||
+                  !aMesh->FindFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                                   nodes[1], nodes[3], nodes[5], nodes[7]) )
+                aMesh->AddFace(nodes[0], nodes[2], nodes[4], nodes[6],
+                               nodes[1], nodes[3], nodes[5], nodes[7]);
+            }
+          }
+          else {
+            int nbPolygonNodes = lastVol.NbFaceNodes( iF );
+            vector<const SMDS_MeshNode*> polygon_nodes (nbPolygonNodes);
+            for (int inode = 0; inode < nbPolygonNodes; inode++) {
+              polygon_nodes[inode] = nodes[inode];
+            }
+            if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
+              aMesh->AddPolygonalFace(polygon_nodes);
           }
-          if (!hasFreeLinks || !aMesh->FindFace(polygon_nodes))
-            aMesh->AddPolygonalFace(polygon_nodes);
         }
         break;
       }
     }
-
   } // loop on swept elements
 }
 
@@ -2355,6 +3018,8 @@ void SMESH_MeshEditor::RotationSweep(set<const SMDS_MeshElement*> & theElems,
   MESSAGE( "RotationSweep()");
   gp_Trsf aTrsf;
   aTrsf.SetRotation( theAxis, theAngle );
+  gp_Trsf aTrsf2;
+  aTrsf2.SetRotation( theAxis, theAngle/2. );
 
   gp_Lin aLine( theAxis );
   double aSqTol = theTol * theTol;
@@ -2367,8 +3032,7 @@ void SMESH_MeshEditor::RotationSweep(set<const SMDS_MeshElement*> & theElems,
 
   // loop on theElems
   set< const SMDS_MeshElement* >::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
     if ( !elem )
       continue;
@@ -2383,8 +3047,7 @@ void SMESH_MeshEditor::RotationSweep(set<const SMDS_MeshElement*> & theElems,
       const SMDS_MeshNode* node =
         static_cast<const SMDS_MeshNode*>( itN->next() );
       TNodeOfNodeListMapItr nIt = mapNewNodes.find( node );
-      if ( nIt == mapNewNodes.end() )
-      {
+      if ( nIt == mapNewNodes.end() ) {
         nIt = mapNewNodes.insert( make_pair( node, list<const SMDS_MeshNode*>() )).first;
         list<const SMDS_MeshNode*>& listNewNodes = nIt->second;
 
@@ -2396,19 +3059,53 @@ void SMESH_MeshEditor::RotationSweep(set<const SMDS_MeshElement*> & theElems,
         const SMDS_MeshNode * newNode = node;
         for ( int i = 0; i < theNbSteps; i++ ) {
           if ( !isOnAxis ) {
-            aTrsf.Transforms( coord[0], coord[1], coord[2] );
+            if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+              // create two nodes
+              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] );
+              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] );
+            }
             newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
           }
-          listNewNodes.push_back( newNode );
+          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;
+            for(int i = 0; i<theNbSteps; i++) {
+              aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+              newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+              listNewNodes.push_back( newNode );
+              aTrsf2.Transforms( coord[0], coord[1], coord[2] );
+              newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+              listNewNodes.push_back( newNode );
+            }
+          }
         }
       }
       newNodesItVec.push_back( nIt );
     }
     // make new elements
-    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
+    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps );
   }
 
-  makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems );
+  makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps );
 
 }
 
@@ -2493,19 +3190,23 @@ void SMESH_MeshEditor::ExtrusionSweep
 {
   SMESHDS_Mesh* aMesh = GetMeshDS();
 
+  int nbsteps = theParams.mySteps->Length();
+
   TNodeOfNodeListMap mapNewNodes;
+  //TNodeOfNodeVecMap mapNewNodes;
   TElemOfVecOfNnlmiMap mapElemNewNodes;
+  //TElemOfVecOfMapNodesMap mapElemNewNodes;
 
   // loop on theElems
   set< const SMDS_MeshElement* >::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     // check element type
     const SMDS_MeshElement* elem = (*itElem);
     if ( !elem )
       continue;
 
     vector<TNodeOfNodeListMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
+    //vector<TNodeOfNodeVecMapItr> & newNodesItVec = mapElemNewNodes[ elem ];
     newNodesItVec.reserve( elem->NbNodes() );
 
     // loop on elem nodes
@@ -2516,15 +3217,33 @@ void SMESH_MeshEditor::ExtrusionSweep
       const SMDS_MeshNode* node =
         static_cast<const SMDS_MeshNode*>( itN->next() );
       TNodeOfNodeListMap::iterator nIt = mapNewNodes.find( node );
-      if ( nIt == mapNewNodes.end() )
-      {
+      //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);
 
         // make new nodes
         double coord[] = { node->X(), node->Y(), node->Z() };
-        int nbsteps = theParams.mySteps->Length();
+        //int nbsteps = theParams.mySteps->Length();
         for ( int i = 0; i < nbsteps; i++ ) {
+          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+            // create additional 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.;
+            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);
+              listNewNodes.push_back( newNode );
+            }
+          }
           //aTrsf.Transforms( coord[0], coord[1], coord[2] );
           coord[0] = coord[0] + theParams.myDir.X()*theParams.mySteps->Value(i+1);
           coord[1] = coord[1] + theParams.myDir.Y()*theParams.mySteps->Value(i+1);
@@ -2533,20 +3252,59 @@ void SMESH_MeshEditor::ExtrusionSweep
             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] );
             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);
+                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] );
+                listNewNodes.push_back( newNode );
+              }
+            }
           }
         }
       }
       newNodesItVec.push_back( nIt );
     }
     // make new elements
-    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
+    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], nbsteps );
   }
   if( theFlags & EXTRUSION_FLAG_BOUNDARY ) {
-    makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems );
+    makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, nbsteps );
   }
 }
 
@@ -2855,6 +3613,14 @@ SMESH_MeshEditor::Extrusion_Error
          }
 
          // make new node
+          if( elem->IsQuadratic() && !elem->IsMediumNode(node) ) {
+            // create additional node
+            double x = ( aPN1.X() + aPN0.X() )/2.;
+            double y = ( aPN1.Y() + aPN0.Y() )/2.;
+            double z = ( aPN1.Z() + aPN0.Z() )/2.;
+            const SMDS_MeshNode* newNode = aMesh->AddNode(x,y,z);
+            listNewNodes.push_back( newNode );
+          }
          aX = aPN1.X();
          aY = aPN1.Y();
          aZ = aPN1.Z();
@@ -2867,13 +3633,44 @@ SMESH_MeshEditor::Extrusion_Error
          aDT0x = aDT1x;
        }
       }
+
+      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()==aNbTP-1) {
+            vector<const SMDS_MeshNode*> aNodes(2*(aNbTP-1));
+            gp_XYZ P(node->X(), node->Y(), node->Z());
+            list< const SMDS_MeshNode* >::iterator it = listNewNodes.begin();
+            int i;
+            for(i=0; i<aNbTP-1; i++) {
+              const SMDS_MeshNode* N = *it;
+              double x = ( N->X() + P.X() )/2.;
+              double y = ( N->Y() + P.Y() )/2.;
+              double z = ( N->Z() + P.Z() )/2.;
+              const SMDS_MeshNode* newN = aMesh->AddNode(x,y,z);
+              aNodes[2*i] = newN;
+              aNodes[2*i+1] = N;
+              P = gp_XYZ(N->X(),N->Y(),N->Z());
+            }
+            listNewNodes.clear();
+            for(i=0; i<2*(aNbTP-1); i++) {
+              listNewNodes.push_back(aNodes[i]);
+            }
+          }
+        }
+      }
+
       newNodesItVec.push_back( nIt );
     }
     // make new elements
-    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem] );
+    sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem],
+                  newNodesItVec[0]->second.size() );
   }
 
-  makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements );
+  makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElements,
+            aNbTP-1 );
 
   return EXTR_OK;
 }
@@ -2908,8 +3705,7 @@ void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
 
   // loop on theElems
   set< const SMDS_MeshElement* >::iterator itElem;
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
     if ( !elem )
       continue;
@@ -2979,8 +3775,7 @@ void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
     { 0, 1, 2, 3, 4, 5, 6, 7 }   // FORWARD
   };
 
-  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
-  {
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
     const SMDS_MeshElement* elem = (*itElem);
     if ( !elem || elem->GetType() == SMDSAbs_Node )
       continue;
@@ -3071,12 +3866,46 @@ void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
       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
     const SMDS_MeshNode* nodes[8];
     int iNode = 0;
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() )
-    {
+    while ( itN->more() ) {
       const SMDS_MeshNode* node =
         static_cast<const SMDS_MeshNode*>( itN->next() );
       TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
@@ -3087,18 +3916,26 @@ void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
     if ( iNode != nbNodes )
       continue; // not all nodes transformed
 
-    if ( theCopy )
-    {
+    if ( theCopy ) {
       // add a new element
       switch ( elemType ) {
       case SMDSAbs_Edge:
-        aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] );
+        if ( nbNodes == 2 )
+          aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] );
+        else
+          aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] );
         break;
       case SMDSAbs_Face:
         if ( nbNodes == 3 )
           aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] );
-        else
+        else if(nbNodes==4)
           aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ]);
+        else if(nbNodes==6)
+          aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                         nodes[4], nodes[5]);
+        else // nbNodes==8
+          aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
+                         nodes[4], nodes[5], nodes[6], nodes[7]);
         break;
       case SMDSAbs_Volume:
         if ( nbNodes == 4 )
@@ -3112,6 +3949,22 @@ void SMESH_MeshEditor::Transform (set<const SMDS_MeshElement*> & theElems,
         else if ( nbNodes == 5 )
           aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
                             nodes[ 4 ]);
+        else if(nbNodes==10)
+          aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
+                           nodes[5], nodes[6], nodes[7], nodes[8], nodes[9]);
+        else if(nbNodes==13)
+          aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
+                           nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
+                           nodes[10], nodes[11], nodes[12]);
+        else if(nbNodes==15)
+          aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
+                           nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
+                           nodes[10], nodes[11], nodes[12], nodes[13], nodes[14]);
+        else // nbNodes==20
+          aMesh->AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4],
+                           nodes[5], nodes[6], nodes[7], nodes[8], nodes[9],
+                           nodes[10], nodes[11], nodes[12], nodes[13], nodes[14],
+                           nodes[15], nodes[16], nodes[17], nodes[18], nodes[19]);
         break;
       default:;
       }
@@ -3275,13 +4128,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
   // Fill nodeNodeMap and elems
 
   TListOfListOfNodes::iterator grIt = theGroupsOfNodes.begin();
-  for ( ; grIt != theGroupsOfNodes.end(); grIt++ )
-  {
+  for ( ; grIt != theGroupsOfNodes.end(); grIt++ ) {
     list<const SMDS_MeshNode*>& nodes = *grIt;
     list<const SMDS_MeshNode*>::iterator nIt = nodes.begin();
     const SMDS_MeshNode* nToKeep = *nIt;
-    for ( ; nIt != nodes.end(); nIt++ )
-    {
+    for ( ; nIt != nodes.end(); nIt++ ) {
       const SMDS_MeshNode* nToRemove = *nIt;
       nodeNodeMap.insert( TNodeNodeMap::value_type( nToRemove, nToKeep ));
       if ( nToRemove != nToKeep ) {
@@ -3290,15 +4141,16 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
       }
 
       SMDS_ElemIteratorPtr invElemIt = nToRemove->GetInverseElementIterator();
-      while ( invElemIt->more() )
-        elems.insert( invElemIt->next() );
+      while ( invElemIt->more() ) {
+        const SMDS_MeshElement* elem = invElemIt->next();
+          elems.insert(elem);
+      }
     }
   }
   // Change element nodes or remove an element
 
   set<const SMDS_MeshElement*>::iterator eIt = elems.begin();
-  for ( ; eIt != elems.end(); eIt++ )
-  {
+  for ( ; eIt != elems.end(); eIt++ ) {
     const SMDS_MeshElement* elem = *eIt;
     int nbNodes = elem->NbNodes();
     int aShapeId = FindShape( elem );
@@ -3309,8 +4161,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
 
     // get new seq of nodes
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
-    while ( itN->more() )
-    {
+    while ( itN->more() ) {
       const SMDS_MeshNode* n =
         static_cast<const SMDS_MeshNode*>( itN->next() );
 
@@ -3330,8 +4181,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
 
     bool isOk = true;
     int nbUniqueNodes = nodeSet.size();
-    if ( nbNodes != nbUniqueNodes ) // some nodes stick
-    {
+    if ( nbNodes != nbUniqueNodes ) { // some nodes stick
       // Polygons and Polyhedral volumes
       if (elem->IsPoly()) {
 
@@ -3360,15 +4210,18 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
                 aMesh->SetMeshElementOnShape(newElem, aShapeId);
             }
             aMesh->ChangeElementNodes(elem, &polygons_nodes[inode], quantities[nbNew - 1]);
-          } else {
+          }
+          else {
             rmElemIds.push_back(elem->GetID());
           }
 
-        } else if (elem->GetType() == SMDSAbs_Volume) {
+        }
+        else if (elem->GetType() == SMDSAbs_Volume) {
           // Polyhedral volume
           if (nbUniqueNodes < 4) {
             rmElemIds.push_back(elem->GetID());
-          } else {
+          }
+          else {
             // each face has to be analized in order to check volume validity
             const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
               static_cast<const SMDS_PolyhedralVolumeOfNodes*>( elem );
@@ -3403,11 +4256,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
               else
                 rmElemIds.push_back(elem->GetID());
 
-            } else {
+            }
+            else {
               rmElemIds.push_back(elem->GetID());
             }
           }
-        } else {
+        }
+        else {
         }
 
         continue;
@@ -3478,7 +4333,96 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
         else
           isOk = false;
         break;
-      case 8: { //////////////////////////////////// HEXAHEDRON
+      case 8: { 
+        if(elem->IsQuadratic()) { // Quadratic quadrangle
+          //   1    5    2
+          //    +---+---+
+          //    |       |
+          //    |       |
+          //   4+       +6
+          //    |       |
+          //    |       |
+          //    +---+---+
+          //   0    7    3
+          isOk = false;
+          if(nbRepl==3) {
+            nbUniqueNodes = 6;
+            if( iRepl[0]==0 && iRepl[1]==1 && iRepl[2]==4 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[2];
+              uniqueNodes[2] = curNodes[3];
+              uniqueNodes[3] = curNodes[5];
+              uniqueNodes[4] = curNodes[6];
+              uniqueNodes[5] = curNodes[7];
+              isOk = true;
+            }
+            if( iRepl[0]==0 && iRepl[1]==3 && iRepl[2]==7 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[1];
+              uniqueNodes[2] = curNodes[2];
+              uniqueNodes[3] = curNodes[4];
+              uniqueNodes[4] = curNodes[5];
+              uniqueNodes[5] = curNodes[6];
+              isOk = true;
+            }
+            if( iRepl[0]==0 && iRepl[1]==4 && iRepl[2]==7 ) {
+              uniqueNodes[0] = curNodes[1];
+              uniqueNodes[1] = curNodes[2];
+              uniqueNodes[2] = curNodes[3];
+              uniqueNodes[3] = curNodes[5];
+              uniqueNodes[4] = curNodes[6];
+              uniqueNodes[5] = curNodes[0];
+              isOk = true;
+            }
+            if( iRepl[0]==1 && iRepl[1]==2 && iRepl[2]==5 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[1];
+              uniqueNodes[2] = curNodes[3];
+              uniqueNodes[3] = curNodes[4];
+              uniqueNodes[4] = curNodes[6];
+              uniqueNodes[5] = curNodes[7];
+              isOk = true;
+            }
+            if( iRepl[0]==1 && iRepl[1]==4 && iRepl[2]==5 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[2];
+              uniqueNodes[2] = curNodes[3];
+              uniqueNodes[3] = curNodes[1];
+              uniqueNodes[4] = curNodes[6];
+              uniqueNodes[5] = curNodes[7];
+              isOk = true;
+            }
+            if( iRepl[0]==2 && iRepl[1]==3 && iRepl[2]==6 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[1];
+              uniqueNodes[2] = curNodes[2];
+              uniqueNodes[3] = curNodes[4];
+              uniqueNodes[4] = curNodes[5];
+              uniqueNodes[5] = curNodes[7];
+              isOk = true;
+            }
+            if( iRepl[0]==2 && iRepl[1]==5 && iRepl[2]==6 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[1];
+              uniqueNodes[2] = curNodes[3];
+              uniqueNodes[3] = curNodes[4];
+              uniqueNodes[4] = curNodes[2];
+              uniqueNodes[5] = curNodes[7];
+              isOk = true;
+            }
+            if( iRepl[0]==3 && iRepl[1]==6 && iRepl[2]==7 ) {
+              uniqueNodes[0] = curNodes[0];
+              uniqueNodes[1] = curNodes[1];
+              uniqueNodes[2] = curNodes[2];
+              uniqueNodes[3] = curNodes[4];
+              uniqueNodes[4] = curNodes[5];
+              uniqueNodes[5] = curNodes[3];
+              isOk = true;
+            }
+          }
+          break;
+        }
+        //////////////////////////////////// HEXAHEDRON
         isOk = false;
         SMDS_VolumeTool hexa (elem);
         hexa.SetExternalNormal();
@@ -3682,11 +4626,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
           }
           aMesh->ChangePolyhedronNodes( elem, poly_nodes, quantities );
         }
-      } else {
+      }
+      else {
         // Change regular element or polygon
         aMesh->ChangeElementNodes( elem, uniqueNodes, nbUniqueNodes );
       }
-    } else {
+    }
+    else {
       // Remove invalid regular element or invalid polygon
       rmElemIds.push_back( elem->GetID() );
     }
@@ -3779,14 +4725,52 @@ const SMDS_MeshElement*
         i1 = iNode - 1;
     }
     // find a n2 linked to n1
-    for ( iNode = 0; iNode < 2; iNode++ ) {
-      if ( iNode ) // node before n1
-        n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
-      else         // node after n1
-        n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
-      if ( n == n2 )
-        return elem;
+    if(!elem->IsQuadratic()) {
+      for ( iNode = 0; iNode < 2; iNode++ ) {
+        if ( iNode ) // node before n1
+          n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
+        else         // node after n1
+          n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
+        if ( n == n2 )
+          return elem;
+      }
     }
+    else { // analysis for quadratic elements
+      bool IsFind = false;
+      // check using only corner nodes
+      for ( iNode = 0; iNode < 2; iNode++ ) {
+        if ( iNode ) // node before n1
+          n = faceNodes[ i1 == 0 ? nbN/2 - 1 : i1 - 1 ];
+        else         // node after n1
+          n = faceNodes[ i1 + 1 == nbN/2 ? 0 : i1 + 1 ];
+        if ( n == n2 )
+          IsFind = true;
+      }
+      if(IsFind) {
+        return elem;
+      }
+      else {
+        // check using all nodes
+        const SMDS_QuadraticFaceOfNodes* F =
+          static_cast<const SMDS_QuadraticFaceOfNodes*>(elem);
+        // use special nodes iterator
+        SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+        while ( anIter->more() ) {
+          faceNodes[iNode] = static_cast<const SMDS_MeshNode*>(anIter->next());
+          if ( faceNodes[ iNode++ ] == n1 )
+            i1 = iNode - 1;
+        }
+        for ( iNode = 0; iNode < 2; iNode++ ) {
+          if ( iNode ) // node before n1
+            n = faceNodes[ i1 == 0 ? nbN - 1 : i1 - 1 ];
+          else         // node after n1
+            n = faceNodes[ i1 + 1 == nbN ? 0 : i1 + 1 ];
+          if ( n == n2 ) {
+            return elem;
+          }
+        }
+      }
+    } // end analysis for quadratic elements
   }
   return 0;
 }
@@ -3830,12 +4814,12 @@ static bool findFreeBorder (const SMDS_MeshNode*                theFirstNode,
   theNodes.push_back( theFirstNode );
   theNodes.push_back( theSecondNode );
 
-  const SMDS_MeshNode* nodes [5], *nIgnore = theFirstNode, * nStart = theSecondNode;
+  //vector<const SMDS_MeshNode*> nodes;
+  const SMDS_MeshNode *nIgnore = theFirstNode, *nStart = theSecondNode;
   set < const SMDS_MeshElement* > foundElems;
   bool needTheLast = ( theLastNode != 0 );
 
-  while ( nStart != theLastNode )
-  {
+  while ( nStart != theLastNode ) {
     if ( nStart == theFirstNode )
       return !needTheLast;
 
@@ -3846,13 +4830,24 @@ static bool findFreeBorder (const SMDS_MeshNode*                theFirstNode,
     SMDS_ElemIteratorPtr invElemIt = nStart->facesIterator();
     while ( invElemIt->more() ) {
       const SMDS_MeshElement* e = invElemIt->next();
-      if ( e == curElem || foundElems.insert( e ).second )
-      {
+      if ( e == curElem || foundElems.insert( e ).second ) {
         // get nodes
-        SMDS_ElemIteratorPtr nIt = e->nodesIterator();
         int iNode = 0, nbNodes = e->NbNodes();
-        while ( nIt->more() )
-          nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+        const SMDS_MeshNode* nodes[nbNodes+1];
+        if(e->IsQuadratic()) {
+          const SMDS_QuadraticFaceOfNodes* F =
+            static_cast<const SMDS_QuadraticFaceOfNodes*>(e);
+          // use special nodes iterator
+          SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+          while( anIter->more() ) {
+            nodes[ iNode++ ] = anIter->next();
+          }
+        }
+        else {
+          SMDS_ElemIteratorPtr nIt = e->nodesIterator();
+          while ( nIt->more() )
+            nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+        }
         nodes[ iNode ] = nodes[ 0 ];
         // check 2 links
         for ( iNode = 0; iNode < nbNodes; iNode++ )
@@ -3987,8 +4982,7 @@ SMESH_MeshEditor::Sew_Error
     MESSAGE(" Free Border 1 not found " );
     aResult = SEW_BORDER1_NOT_FOUND;
   }
-  if (theSideIsFreeBorder)
-  {
+  if (theSideIsFreeBorder) {
     // Free border 2
     // --------------
     if (!findFreeBorder(theSideFirstNode, theSideSecondNode, theSideThirdNode,
@@ -4000,8 +4994,7 @@ SMESH_MeshEditor::Sew_Error
   if ( aResult != SEW_OK )
     return aResult;
 
-  if (!theSideIsFreeBorder)
-  {
+  if (!theSideIsFreeBorder) {
     // Side 2
     // --------------
 
@@ -4027,8 +5020,7 @@ SMESH_MeshEditor::Sew_Error
     gp_XYZ Ps2( theSideSecondNode->X(), theSideSecondNode->Y(), theSideSecondNode->Z() );
     double tol2 = 1.e-8;
     gp_Vec Vbs1( Pb1 - Ps1 ),Vbs2( Pb2 - Ps2 );
-    if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 )
-    {
+    if ( Vbs1.SquareMagnitude() > tol2 || Vbs2.SquareMagnitude() > tol2 ) {
       // Need node movement.
 
       // find X and Z axes to create trsf
@@ -4057,8 +5049,7 @@ SMESH_MeshEditor::Sew_Error
         nBordXYZ.insert( TNodeXYZMap::value_type( n, xyz ));
       }
     }
-    else
-    {
+    else {
       // just insert nodes XYZ in the nBordXYZ map
       for ( nBordIt = bordNodes.begin(); nBordIt != bordNodes.end(); nBordIt++ ) {
         const SMDS_MeshNode* n = *nBordIt;
@@ -4110,13 +5101,27 @@ SMESH_MeshEditor::Sew_Error
         const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : faceNodes;
         if ( isVolume ) // --volume
           hasVolumes = true;
-        else if ( nbNodes > 2 ) { // --face
+        //else if ( nbNodes > 2 ) { // --face
+        else if ( elem->GetType()==SMDSAbs_Face ) { // --face
           // retrieve all face nodes and find iPrevNode - an index of the prevSideNode
-          SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
-          while ( nIt->more() ) {
-            nodes[ iNode ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
-            if ( nodes[ iNode++ ] == prevSideNode )
-              iPrevNode = iNode - 1;
+          if(elem->IsQuadratic()) {
+            const SMDS_QuadraticFaceOfNodes* F =
+              static_cast<const SMDS_QuadraticFaceOfNodes*>(elem);
+            // use special nodes iterator
+            SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+            while( anIter->more() ) {
+              nodes[ iNode ] = anIter->next();
+              if ( nodes[ iNode++ ] == prevSideNode )
+                iPrevNode = iNode - 1;
+            }
+          }
+          else {
+            SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
+            while ( nIt->more() ) {
+              nodes[ iNode ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
+              if ( nodes[ iNode++ ] == prevSideNode )
+                iPrevNode = iNode - 1;
+            }
           }
           // there are 2 links to check
           nbNodes = 2;
@@ -4129,7 +5134,8 @@ SMESH_MeshEditor::Sew_Error
           if ( isVolume ) {
             if ( !volume.IsLinked( n, prevSideNode ))
               continue;
-          } else {
+          }
+          else {
             if ( iNode ) // a node before prevSideNode
               n = nodes[ iPrevNode == 0 ? elem->NbNodes() - 1 : iPrevNode - 1 ];
             else         // a node after prevSideNode
@@ -4408,18 +5414,39 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
   int iNode = 0, il1, il2, i3, i4;
   il1 = il2 = i3 = i4 = -1;
   const SMDS_MeshNode* nodes[ theFace->NbNodes() ];
-  SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
-  while ( nodeIt->more() ) {
-    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-    if ( n == theBetweenNode1 )
-      il1 = iNode;
-    else if ( n == theBetweenNode2 )
-      il2 = iNode;
-    else if ( i3 < 0 )
-      i3 = iNode;
-    else
-      i4 = iNode;
-    nodes[ iNode++ ] = n;
+
+  if(theFace->IsQuadratic()) {
+    const SMDS_QuadraticFaceOfNodes* F =
+      static_cast<const SMDS_QuadraticFaceOfNodes*>(theFace);
+    // use special nodes iterator
+    SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+    while( anIter->more() ) {
+      const SMDS_MeshNode* n = anIter->next();
+      if ( n == theBetweenNode1 )
+        il1 = iNode;
+      else if ( n == theBetweenNode2 )
+        il2 = iNode;
+      else if ( i3 < 0 )
+        i3 = iNode;
+      else
+        i4 = iNode;
+      nodes[ iNode++ ] = n;
+    }
+  }
+  else {
+    SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
+    while ( nodeIt->more() ) {
+      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+      if ( n == theBetweenNode1 )
+        il1 = iNode;
+      else if ( n == theBetweenNode2 )
+        il2 = iNode;
+      else if ( i3 < 0 )
+        i3 = iNode;
+      else
+        i4 = iNode;
+      nodes[ iNode++ ] = n;
+    }
   }
   if ( il1 < 0 || il2 < 0 || i3 < 0 )
     return ;
@@ -4448,25 +5475,48 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
 
     // add nodes of face up to first node of link
     bool isFLN = false;
-    nodeIt = theFace->nodesIterator();
-    while ( nodeIt->more() && !isFLN ) {
-      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-      poly_nodes[iNode++] = n;
-      if (n == nodes[il1]) {
-        isFLN = true;
-      }
-    }
 
-    // add nodes to insert
-    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-    for (; nIt != aNodesToInsert.end(); nIt++) {
-      poly_nodes[iNode++] = *nIt;
+    if(theFace->IsQuadratic()) {
+      const SMDS_QuadraticFaceOfNodes* F =
+        static_cast<const SMDS_QuadraticFaceOfNodes*>(theFace);
+      // use special nodes iterator
+      SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+      while( anIter->more()  && !isFLN ) {
+        const SMDS_MeshNode* n = anIter->next();
+        poly_nodes[iNode++] = n;
+        if (n == nodes[il1]) {
+          isFLN = true;
+        }
+      }
+      // add nodes to insert
+      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+      for (; nIt != aNodesToInsert.end(); nIt++) {
+        poly_nodes[iNode++] = *nIt;
+      }
+      // add nodes of face starting from last node of link
+      while ( anIter->more() ) {
+        poly_nodes[iNode++] = anIter->next();
+      }
     }
-
-    // add nodes of face starting from last node of link
-    while ( nodeIt->more() ) {
-      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-      poly_nodes[iNode++] = n;
+    else {
+      SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
+      while ( nodeIt->more() && !isFLN ) {
+        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+        poly_nodes[iNode++] = n;
+        if (n == nodes[il1]) {
+          isFLN = true;
+        }
+      }
+      // add nodes to insert
+      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+      for (; nIt != aNodesToInsert.end(); nIt++) {
+        poly_nodes[iNode++] = *nIt;
+      }
+      // add nodes of face starting from last node of link
+      while ( nodeIt->more() ) {
+        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+        poly_nodes[iNode++] = n;
+      }
     }
 
     // edit or replace the face
@@ -4474,8 +5524,8 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
 
     if (theFace->IsPoly()) {
       aMesh->ChangePolygonNodes(theFace, poly_nodes);
-
-    else {
+    }
+    else {
       int aShapeId = FindShape( theFace );
 
       SMDS_MeshElement* newElem = aMesh->AddPolygonalFace(poly_nodes);
@@ -4487,81 +5537,184 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     return;
   }
 
-  // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
-  int nbLinkNodes = 2 + aNodesToInsert.size();
-  const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
-  linkNodes[ 0 ] = nodes[ il1 ];
-  linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
-  list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-  for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
-    linkNodes[ iNode++ ] = *nIt;
-  }
-  // decide how to split a quadrangle: compare possible variants
-  // and choose which of splits to be a quadrangle
-  int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
-  if ( nbFaceNodes == 3 )
-  {
-    iBestQuad = nbSplits;
-    i4 = i3;
-  }
-  else if ( nbFaceNodes == 4 )
-  {
-    SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
-    double aBestRate = DBL_MAX;
-    for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
-      i1 = 0; i2 = 1;
-      double aBadRate = 0;
-      // evaluate elements quality
-      for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
-        if ( iSplit == iQuad ) {
-          SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
-                                 linkNodes[ i2++ ],
-                                 nodes[ i3 ],
-                                 nodes[ i4 ]);
-          aBadRate += getBadRate( &quad, aCrit );
+  if( !theFace->IsQuadratic() ) {
+
+    // put aNodesToInsert between theBetweenNode1 and theBetweenNode2
+    int nbLinkNodes = 2 + aNodesToInsert.size();
+    const SMDS_MeshNode* linkNodes[ nbLinkNodes ];
+    linkNodes[ 0 ] = nodes[ il1 ];
+    linkNodes[ nbLinkNodes - 1 ] = nodes[ il2 ];
+    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+    for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
+      linkNodes[ iNode++ ] = *nIt;
+    }
+    // decide how to split a quadrangle: compare possible variants
+    // and choose which of splits to be a quadrangle
+    int i1, i2, iSplit, nbSplits = nbLinkNodes - 1, iBestQuad;
+    if ( nbFaceNodes == 3 ) {
+      iBestQuad = nbSplits;
+      i4 = i3;
+    }
+    else if ( nbFaceNodes == 4 ) {
+      SMESH::Controls::NumericalFunctorPtr aCrit( new SMESH::Controls::AspectRatio);
+      double aBestRate = DBL_MAX;
+      for ( int iQuad = 0; iQuad < nbSplits; iQuad++ ) {
+        i1 = 0; i2 = 1;
+        double aBadRate = 0;
+        // evaluate elements quality
+        for ( iSplit = 0; iSplit < nbSplits; iSplit++ ) {
+          if ( iSplit == iQuad ) {
+            SMDS_FaceOfNodes quad (linkNodes[ i1++ ],
+                                   linkNodes[ i2++ ],
+                                   nodes[ i3 ],
+                                   nodes[ i4 ]);
+            aBadRate += getBadRate( &quad, aCrit );
+          }
+          else {
+            SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
+                                   linkNodes[ i2++ ],
+                                   nodes[ iSplit < iQuad ? i4 : i3 ]);
+            aBadRate += getBadRate( &tria, aCrit );
+          }
         }
-        else {
-          SMDS_FaceOfNodes tria (linkNodes[ i1++ ],
-                                 linkNodes[ i2++ ],
-                                 nodes[ iSplit < iQuad ? i4 : i3 ]);
-          aBadRate += getBadRate( &tria, aCrit );
+        // choice
+        if ( aBadRate < aBestRate ) {
+          iBestQuad = iQuad;
+          aBestRate = aBadRate;
         }
       }
-      // choice
-      if ( aBadRate < aBestRate ) {
-        iBestQuad = iQuad;
-        aBestRate = aBadRate;
+    }
+    
+    // create new elements
+    SMESHDS_Mesh *aMesh = GetMeshDS();
+    int aShapeId = FindShape( theFace );
+    
+    i1 = 0; i2 = 1;
+    for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
+      SMDS_MeshElement* newElem = 0;
+      if ( iSplit == iBestQuad )
+        newElem = aMesh->AddFace (linkNodes[ i1++ ],
+                                  linkNodes[ i2++ ],
+                                  nodes[ i3 ],
+                                  nodes[ i4 ]);
+      else
+        newElem = aMesh->AddFace (linkNodes[ i1++ ],
+                                  linkNodes[ i2++ ],
+                                  nodes[ iSplit < iBestQuad ? i4 : i3 ]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+    }
+    
+    // change nodes of theFace
+    const SMDS_MeshNode* newNodes[ 4 ];
+    newNodes[ 0 ] = linkNodes[ i1 ];
+    newNodes[ 1 ] = linkNodes[ i2 ];
+    newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
+    newNodes[ 3 ] = nodes[ i4 ];
+    aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
+  } // end if(!theFace->IsQuadratic())
+  else { // theFace is quadratic
+    // we have to split theFace on simple triangles and one simple quadrangle
+    int tmp = il1/2;
+    int nbshift = tmp*2;
+    // shift nodes in nodes[] by nbshift
+    int i,j;
+    for(i=0; i<nbshift; i++) {
+      const SMDS_MeshNode* n = nodes[0];
+      for(j=0; j<nbFaceNodes-1; j++) {
+        nodes[j] = nodes[j+1];
       }
+      nodes[nbFaceNodes-1] = n;
     }
-  }
+    il1 = il1 - nbshift;
+    // now have to insert nodes between n0 and n1 or n1 and n2 (see below)
+    //   n0      n1     n2    n0      n1     n2
+    //     +-----+-----+        +-----+-----+ 
+    //      \         /         |           |
+    //       \       /          |           |
+    //      n5+     +n3       n7+           +n3
+    //         \   /            |           |
+    //          \ /             |           |
+    //           +              +-----+-----+
+    //           n4           n6      n5     n4
+
+    // create new elements
+    SMESHDS_Mesh *aMesh = GetMeshDS();
+    int aShapeId = FindShape( theFace );
 
-  // create new elements
-  SMESHDS_Mesh *aMesh = GetMeshDS();
-  int aShapeId = FindShape( theFace );
-
-  i1 = 0; i2 = 1;
-  for ( iSplit = 0; iSplit < nbSplits - 1; iSplit++ ) {
-    SMDS_MeshElement* newElem = 0;
-    if ( iSplit == iBestQuad )
-      newElem = aMesh->AddFace (linkNodes[ i1++ ],
-                                linkNodes[ i2++ ],
-                                nodes[ i3 ],
-                                nodes[ i4 ]);
-    else
-      newElem = aMesh->AddFace (linkNodes[ i1++ ],
-                                linkNodes[ i2++ ],
-                                nodes[ iSplit < iBestQuad ? i4 : i3 ]);
-    if ( aShapeId && newElem )
-      aMesh->SetMeshElementOnShape( newElem, aShapeId );
+    int n1,n2,n3;
+    if(nbFaceNodes==6) { // quadratic triangle
+      SMDS_MeshElement* newElem =
+        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      if(theFace->IsMediumNode(nodes[il1])) {
+        // create quadrangle
+        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[5]);
+        if ( aShapeId && newElem )
+          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        n1 = 1;
+        n2 = 2;
+        n3 = 3;
+      }
+      else {
+        // create quadrangle
+        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[5]);
+        if ( aShapeId && newElem )
+          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        n1 = 0;
+        n2 = 1;
+        n3 = 5;
+      }
+    }
+    else { // nbFaceNodes==8 - quadratic quadrangle
+      SMDS_MeshElement* newElem =
+        aMesh->AddFace(nodes[3],nodes[4],nodes[5]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      newElem = aMesh->AddFace(nodes[5],nodes[6],nodes[7]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      newElem = aMesh->AddFace(nodes[5],nodes[7],nodes[3]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+      if(theFace->IsMediumNode(nodes[il1])) {
+        // create quadrangle
+        newElem = aMesh->AddFace(nodes[0],nodes[1],nodes[3],nodes[7]);
+        if ( aShapeId && newElem )
+          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        n1 = 1;
+        n2 = 2;
+        n3 = 3;
+      }
+      else {
+        // create quadrangle
+        newElem = aMesh->AddFace(nodes[1],nodes[2],nodes[3],nodes[7]);
+        if ( aShapeId && newElem )
+          aMesh->SetMeshElementOnShape( newElem, aShapeId );
+        n1 = 0;
+        n2 = 1;
+        n3 = 7;
+      }
+    }
+    // create needed triangles using n1,n2,n3 and inserted nodes
+    int nbn = 2 + aNodesToInsert.size();
+    const SMDS_MeshNode* aNodes[nbn];
+    aNodes[0] = nodes[n1];
+    aNodes[nbn-1] = nodes[n2];
+    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+    for ( iNode = 1; nIt != aNodesToInsert.end(); nIt++ ) {
+      aNodes[iNode++] = *nIt;
+    }
+    for(i=1; i<nbn; i++) {
+      SMDS_MeshElement* newElem =
+        aMesh->AddFace(aNodes[i-1],aNodes[i],nodes[n3]);
+      if ( aShapeId && newElem )
+        aMesh->SetMeshElementOnShape( newElem, aShapeId );
+    }
+    // remove old quadratic face
+    aMesh->RemoveElement(theFace);
   }
-
-  // change nodes of theFace
-  const SMDS_MeshNode* newNodes[ 4 ];
-  newNodes[ 0 ] = linkNodes[ i1 ];
-  newNodes[ 1 ] = linkNodes[ i2 ];
-  newNodes[ 2 ] = nodes[ iSplit >= iBestQuad ? i3 : i4 ];
-  newNodes[ 3 ] = nodes[ i4 ];
-  aMesh->ChangeElementNodes( theFace, newNodes, iSplit == iBestQuad ? 4 : 3 );
 }
 
 //=======================================================================
@@ -4607,7 +5760,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
                 poly_nodes.push_back(*nIt);
               }
             }
-          } else if (faceNodes[inode] == theBetweenNode2) {
+          }
+          else if (faceNodes[inode] == theBetweenNode2) {
             if (faceNodes[inode + 1] == theBetweenNode1) {
               nbInserted = theNodesToInsert.size();
 
@@ -4619,7 +5773,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
               }
               poly_nodes.push_back(*nIt);
             }
-          } else {
+          }
+          else {
           }
         }
       }
@@ -4632,7 +5787,8 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
     if (elem->IsPoly()) {
       aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
 
-    } else {
+    }
+    else {
       int aShapeId = FindShape( elem );
 
       SMDS_MeshElement* newElem =
@@ -4709,11 +5865,24 @@ SMESH_MeshEditor::Sew_Error
       if ( elem->GetType() == SMDSAbs_Face ) {
         faceSet->insert( elem );
         set <const SMDS_MeshNode*> faceNodeSet;
-        SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
-        while ( nodeIt->more() ) {
-          const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-          nodeSet->insert( n );
-          faceNodeSet.insert( n );
+        if(elem->IsQuadratic()) {
+          const SMDS_QuadraticFaceOfNodes* F =
+            static_cast<const SMDS_QuadraticFaceOfNodes*>(elem);
+          // use special nodes iterator
+          SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+          while( anIter->more() ) {
+            const SMDS_MeshNode* n = anIter->next();
+            nodeSet->insert( n );
+            faceNodeSet.insert( n );
+          }
+        }
+        else {
+          SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+          while ( nodeIt->more() ) {
+            const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+            nodeSet->insert( n );
+            faceNodeSet.insert( n );
+          }
         }
         setOfFaceNodeSet.insert( faceNodeSet );
       }
@@ -4754,8 +5923,7 @@ SMESH_MeshEditor::Sew_Error
     //     face does not exist
     // -------------------------------------------------------------------------
 
-    if ( !volSet->empty() )
-    {
+    if ( !volSet->empty() ) {
       //int nodeSetSize = nodeSet->size();
 
       // loop on given volumes
@@ -4778,9 +5946,11 @@ SMESH_MeshEditor::Sew_Error
             // 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 ) {
+            }
+            else if ( nbNodes == 4 ) {
               aFreeFace = aMesh->FindFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
-            } else {
+            }
+            else {
               vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
               for (int inode = 0; inode < nbNodes; inode++) {
                 poly_nodes[inode] = fNodes[inode];
@@ -4792,9 +5962,11 @@ SMESH_MeshEditor::Sew_Error
             // create a temporary face
             if ( nbNodes == 3 ) {
               aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2] );
-            } else if ( nbNodes == 4 ) {
+            }
+            else if ( nbNodes == 4 ) {
               aFreeFace = aTmpFacesMesh.AddFace( fNodes[0],fNodes[1],fNodes[2],fNodes[3] );
-            } else {
+            }
+            else {
               vector<const SMDS_MeshNode *> poly_nodes (nbNodes);
               for (int inode = 0; inode < nbNodes; inode++) {
                 poly_nodes[inode] = fNodes[inode];
@@ -4946,8 +6118,7 @@ SMESH_MeshEditor::Sew_Error
   // loop on links in linkList; find faces by links and append links
   // of the found faces to linkList
   list< TPairOfNodes >::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]++ ) {
     TPairOfNodes link[] = { *linkIt[0], *linkIt[1] };
     long linkID = aLinkID_Gen.GetLinkID( link[0].first, link[0].second );
     if ( linkIdSet.find( linkID ) == linkIdSet.end() )
@@ -4959,8 +6130,12 @@ SMESH_MeshEditor::Sew_Error
     // ---------------------------------------------------------------
 
     const SMDS_MeshElement* face[] = { 0, 0 };
-    const SMDS_MeshNode* faceNodes[ 2 ][ 5 ];
-    const SMDS_MeshNode* notLinkNodes[ 2 ][ 2 ] = {{ 0, 0 },{ 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);
     int iLinkNode[2][2];
     for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
       const SMDS_MeshNode* n1 = link[iSide].first;
@@ -4984,40 +6159,109 @@ SMESH_MeshEditor::Sew_Error
             faceSet->erase( f );
             // get face nodes and find ones of a link
             iNode = 0;
-            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;
-              faceNodes[ iSide ][ iNode++ ] = n;
+            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_QuadraticFaceOfNodes* F =
+                static_cast<const SMDS_QuadraticFaceOfNodes*>(f);
+              // use special nodes iterator
+              SMDS_NodeIteratorPtr anIter = F->interlacedNodesIterator();
+              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];
             }
-            faceNodes[ iSide ][ iNode ] = faceNodes[ iSide ][ 0 ];
           }
         }
       }
     }
+
     // check similarity of elements of the sides
     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
+      if ( nReplaceMap.size() == 2 ) // faces on input nodes not found
         aResult = ( face[0] ? SEW_BAD_SIDE2_NODES : SEW_BAD_SIDE1_NODES );
-      else
+      }
+      else {
         aResult = SEW_TOPO_DIFF_SETS_OF_ELEMENTS;
+      }
       break; // do not return because it s necessary to remove tmp faces
     }
 
     // set nodes to merge
     // -------------------
 
-    if ( face[0] && face[1] )
-    {
+    if ( face[0] && face[1] )  {
       int nbNodes = face[0]->NbNodes();
       if ( nbNodes != face[1]->NbNodes() ) {
         MESSAGE("Diff nb of face nodes");
@@ -5025,9 +6269,12 @@ SMESH_MeshEditor::Sew_Error
         break; // do not return because it s necessary to remove tmp faces
       }
       bool reverse[] = { false, false }; // order of notLinkNodes of quadrangle
-      if ( nbNodes == 3 )
+      if ( nbNodes == 3 ) {
+        //nReplaceMap.insert( TNodeNodeMap::value_type
+        //                   ( notLinkNodes[0][0], notLinkNodes[1][0] ));
         nReplaceMap.insert( TNodeNodeMap::value_type
-                           ( notLinkNodes[0][0], notLinkNodes[1][0] ));
+                           ( notLinkNodes1[0], notLinkNodes2[0] ));
+      }
       else {
         for ( iSide = 0; iSide < 2; iSide++ ) { // loop on 2 sides
           // analyse link orientation in faces
@@ -5041,34 +6288,44 @@ SMESH_MeshEditor::Sew_Error
             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] ));
+          //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] ));
+          //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] ));
+          }
         }
       }
 
       // 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] );
+      //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] );
         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 = nodes[ iNode ];
+          //const SMDS_MeshNode* n2 = nodes[ iNode + 1];
+          const SMDS_MeshNode* n1 = fnodes1[ iNode ];
+          const SMDS_MeshNode* n2 = fnodes1[ iNode + 1];
           linkList[0].push_back ( TPairOfNodes( n1, n2 ));
           linkList[1].push_back ( TPairOfNodes( nReplaceMap[n1], nReplaceMap[n2] ));
         }
@@ -5100,8 +6357,7 @@ SMESH_MeshEditor::Sew_Error
   // loop on nodes replacement map
   TNodeNodeMap::iterator nReplaceMapIt = nReplaceMap.begin(), nnIt;
   for ( ; nReplaceMapIt != nReplaceMap.end(); nReplaceMapIt++ )
-    if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second )
-    {
+    if ( (*nReplaceMapIt).first != (*nReplaceMapIt).second ) {
       const SMDS_MeshNode* nToRemove = (*nReplaceMapIt).first;
       nodeIDsToRemove.push_back( nToRemove->GetID() );
       // loop on elements sharing nToRemove
@@ -5128,7 +6384,7 @@ SMESH_MeshEditor::Sew_Error
         if ( nbReplaced )
           aMesh->ChangeElementNodes( e, nodes, nbNodes );
       }
-  }
+    }
 
   Remove( nodeIDsToRemove, true );
 
index 6a70e8d5e509a88caf5f5c78482d47e47ae40d86..512a0ca7d4500ff1eb54c2c5bda7e902683f9f08 100755 (executable)
@@ -388,6 +388,35 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
       anActor = myActor;
     if (anActor != 0)
     {
+      // skl 07.02.2006
+      SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh();
+      if( myFilterType == SMESHGUI_TriaFilter || 
+         myFilterType == SMESHGUI_QuadFilter ||
+         myFilterType == SMESHGUI_FaceFilter ) {
+       SMDS_FaceIteratorPtr it = aMesh->facesIterator();
+       while(it->more()) {
+         const SMDS_MeshFace* f = it->next();
+         if(myFilterType == SMESHGUI_FaceFilter) {
+           myIds.Add(f->GetID());
+         }
+         else if( myFilterType==SMESHGUI_TriaFilter &&
+                  ( f->NbNodes()==3 || f->NbNodes()==6 ) ) {
+           myIds.Add(f->GetID());
+         }
+         else if( myFilterType==SMESHGUI_QuadFilter &&
+                  ( f->NbNodes()==4 || f->NbNodes()==8 ) ) {
+           myIds.Add(f->GetID());
+         }
+       }
+      }
+      else if(myFilterType == SMESHGUI_VolumeFilter) {
+       SMDS_VolumeIteratorPtr it = aMesh->volumesIterator();
+       while(it->more()) {
+         const SMDS_MeshVolume* f = it->next();
+         myIds.Add(f->GetID());
+       }
+      }
+      /* commented by skl 07.02.2006
       TVisualObjPtr aVisualObj = anActor->GetObject();
       vtkUnstructuredGrid* aGrid = aVisualObj->GetUnstructuredGrid();
       if (aGrid != 0) {
@@ -411,6 +440,7 @@ SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
           }
         }
       }
+      */
     }
   }
 
index e0d879a73eb47e88882c5e679c779bcd5be3adca..d210078161630cef6588ae51041270871f7b4667 100644 (file)
@@ -51,6 +51,7 @@ EXPORT_HEADERS = \
        StdMeshers_AutomaticLength.hxx \
        StdMeshers_Distribution.hxx \
        StdMeshers_QuadranglePreference.hxx \
+       StdMeshers_Helper.hxx \
        StdMeshers_QuadraticMesh.hxx
 
 EXPORT_PYSCRIPTS =
@@ -78,6 +79,7 @@ LIB_SRC = \
        StdMeshers_AutomaticLength.cxx \
        StdMeshers_Distribution.cxx \
        StdMeshers_QuadranglePreference.cxx \
+       StdMeshers_Helper.cxx \
        StdMeshers_QuadraticMesh.cxx
 
 LIB_SERVER_IDL = 
diff --git a/src/StdMeshers/StdMeshers_Helper.cxx b/src/StdMeshers/StdMeshers_Helper.cxx
new file mode 100644 (file)
index 0000000..219f8c4
--- /dev/null
@@ -0,0 +1,433 @@
+// File:      StdMeshers_Helper.cxx
+// Created:   15.02.06 15:22:41
+// Author:    Sergey KUUL
+// Copyright: Open CASCADE 2006
+
+
+#include "StdMeshers_Helper.hxx"
+
+#include "TopTools_MapOfShape.hxx"
+#include "BRepTools.hxx"
+#include "BRepTools_WireExplorer.hxx"
+#include "SMDS_FacePosition.hxx"
+#include "SMDS_EdgePosition.hxx"
+#include "SMESH_subMesh.hxx"
+#include "Geom2d_Curve.hxx"
+#include "Geom_Curve.hxx"
+#include "Geom_Surface.hxx"
+#include "BRep_Tool.hxx"
+#include "gp_Pnt2d.hxx"
+
+
+//=======================================================================
+//function : CheckShape
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Helper::IsQuadraticSubMesh(const TopoDS_Shape& aSh,
+                                           const bool QuadMode)
+{
+  SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
+  myShapeID = meshDS->ShapeToIndex(aSh);
+  myCreateQuadratic = false;
+  if(QuadMode) {
+    // we can create quadratic elements only if each elements
+    // created on given shape is quadratic
+    // also we have to fill myNLinkNodeMap
+    myCreateQuadratic = true;
+    if(aSh.ShapeType()!=TopAbs_FACE) {
+      for (TopExp_Explorer exp(aSh, TopAbs_FACE); exp.More() && myCreateQuadratic; exp.Next()) {
+        const TopoDS_Face& F = TopoDS::Face(exp.Current());
+        SMDS_ElemIteratorPtr itf = GetMesh()->GetSubMesh(F)->GetSubMeshDS()->GetElements();
+        while(itf->more()) {
+          const SMDS_MeshElement* f = itf->next();
+          if( f->GetType()==SMDSAbs_Face && !f->IsQuadratic() ) {
+            myCreateQuadratic = false;
+            break;
+          }
+          SMDS_ElemIteratorPtr itn = f->nodesIterator();
+          if(f->NbNodes()==6) {
+            const SMDS_MeshNode* Ns[6];
+            int i = 0;
+            while(itn->more()) {
+              Ns[i++] = static_cast<const SMDS_MeshNode*>( itn->next() );
+            }
+            AddNLinkNode(Ns[0],Ns[1],Ns[3]);
+            AddNLinkNode(Ns[1],Ns[2],Ns[4]);
+            AddNLinkNode(Ns[2],Ns[0],Ns[5]);
+          }
+          else if(f->NbNodes()==8) {
+            const SMDS_MeshNode* Ns[8];
+            int i = 0;
+            while(itn->more()) {
+              Ns[i++] = static_cast<const SMDS_MeshNode*>( itn->next() );
+            }
+            AddNLinkNode(Ns[0],Ns[1],Ns[4]);
+            AddNLinkNode(Ns[1],Ns[2],Ns[5]);
+            AddNLinkNode(Ns[2],Ns[3],Ns[6]);
+            AddNLinkNode(Ns[3],Ns[0],Ns[7]);
+          }
+        }
+      }
+    }
+    else {
+      TopTools_MapOfShape aMap;
+      // check edges
+      const TopoDS_Face& F = TopoDS::Face(aSh);
+      const TopoDS_Wire& W = BRepTools::OuterWire(F);
+      BRepTools_WireExplorer wexp (W, F);
+      for (wexp.Init(W, F); wexp.More() && myCreateQuadratic; wexp.Next()) {
+        const TopoDS_Edge& E = wexp.Current();
+        if(aMap.Contains(E))
+          continue;
+        aMap.Add(E);
+        SMDS_ElemIteratorPtr it = GetMesh()->GetSubMesh(E)->GetSubMeshDS()->GetElements();
+        while(it->more()) {
+          const SMDS_MeshElement* e = it->next();
+          if( e->GetType()==SMDSAbs_Edge && !e->IsQuadratic() ) {
+            myCreateQuadratic = false;
+            break;
+          }
+          // fill NLinkNodeMap
+          SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
+          const SMDS_MeshNode* n1 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+          const SMDS_MeshNode* n2 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+          const SMDS_MeshNode* n3 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+          NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+          myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3));
+          myNLinkNodeMap[link] = n3;
+        }
+      }
+    }
+  }
+
+  if(!myCreateQuadratic) {
+    myNLinkNodeMap.clear();
+  }
+
+  return myCreateQuadratic;
+}
+
+
+//=======================================================================
+//function : IsMedium
+//purpose  : 
+//=======================================================================
+
+bool StdMeshers_Helper::IsMedium(const SMDS_MeshNode* n)
+{
+  SMDS_ElemIteratorPtr it = n->GetInverseElementIterator();
+  while (it->more()) {
+    const SMDS_MeshElement* elem = it->next();
+    return elem->IsMediumNode(n);
+  }
+  return false;
+}
+
+
+//=======================================================================
+//function : AddNLinkNode
+//purpose  : 
+//=======================================================================
+/*!
+ * Auxilary function for filling myNLinkNodeMap
+ */
+void StdMeshers_Helper::AddNLinkNode(const SMDS_MeshNode* n1,
+                                     const SMDS_MeshNode* n2,
+                                     const SMDS_MeshNode* n12)
+{
+  NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+  ItNLinkNode itLN = myNLinkNodeMap.find( link );
+  if ( itLN == myNLinkNodeMap.end() ) {
+    // add new record to map
+    myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
+  }
+}
+
+
+//=======================================================================
+//function : GetNodeUV
+//purpose  : 
+//=======================================================================
+/*!
+ * Auxilary function for GetMediumNode()
+ */
+gp_XY StdMeshers_Helper::GetNodeUV(const TopoDS_Face& F,
+                                   const SMDS_MeshNode* n)
+{
+  gp_Pnt2d p2d;
+  const SMDS_PositionPtr Pos = n->GetPosition();
+  if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE) {
+//cout<<"face"<<endl;
+    // node has position on face
+    const SMDS_FacePosition* fpos =
+      static_cast<const SMDS_FacePosition*>(n->GetPosition().get());
+    p2d = gp_Pnt2d(fpos->GetUParameter(),fpos->GetVParameter());
+//cout<<"fpos->GetUParameter()="<<fpos->GetUParameter()<<" fpos->GetVParameter()="<<fpos->GetVParameter()<<endl;
+  }
+  else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) {
+    // node has position on edge => it is needed to find
+    // corresponding edge from face, get pcurve for this
+    // edge and recieve value from this pcurve
+    const SMDS_EdgePosition* epos =
+      static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
+    double param = epos->GetUParameter();
+    SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
+    int edgeID = Pos->GetShapeId();
+    const TopoDS_Edge& E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
+    double f, l;
+    Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+    p2d = C2d->Value(param);
+  }
+  else { // vertex position
+    SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+    const TopoDS_Wire& W = BRepTools::OuterWire(F);
+    BRepTools_WireExplorer wexp (W, F);
+    TopoDS_Edge E;
+    for (wexp.Init(W, F); wexp.More(); wexp.Next()) {
+      E = wexp.Current();
+      TopoDS_Vertex V1 = TopExp::FirstVertex(E);
+      TopoDS_Vertex V2 = TopExp::LastVertex(E);
+      if( meshDS->ShapeToIndex(V1) != Pos->GetShapeId() &&
+          meshDS->ShapeToIndex(V2) != Pos->GetShapeId() ) continue;
+      double f2, l2;
+      Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f2, l2);
+      double f, l;
+      TopLoc_Location L;
+      Handle(Geom_Curve) C = BRep_Tool::Curve(E, L, f, l);
+      gp_Pnt P = C->Value(f);                                                                          
+      if(!L.IsIdentity()) P = P.Transformed(L.Transformation());
+      double tol = BRep_Tool::Tolerance(E);
+      double dx = n->X() - P.X();
+      double dy = n->Y() - P.Y();
+      double dz = n->Z() - P.Z();
+      double dist = sqrt(dx*dx + dy*dy + dz*dz);
+      if(dist<tol) {
+        p2d = C2d->Value(f2);
+      }
+      else {
+        p2d = C2d->Value(l2);
+      }
+    }
+  }
+  return p2d.XY();
+}
+
+
+//=======================================================================
+//function : GetMediumNode
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for search or creation medium node
+ */
+const SMDS_MeshNode* StdMeshers_Helper::GetMediumNode(const SMDS_MeshNode* n1,
+                                                      const SMDS_MeshNode* n2,
+                                                      const bool force3d)
+{
+//cout<<"n1: "<<n1;
+//cout<<"n2: "<<n2;
+  NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+  ItNLinkNode itLN = myNLinkNodeMap.find( link );
+  if ( itLN != myNLinkNodeMap.end() ) {
+    return (*itLN).second;
+  }
+  else {
+    // create medium node
+    SMDS_MeshNode* n12;
+    SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
+    if(!force3d) {
+      // we try to create medium node using UV parameters of
+      // nodes, else - medium between corresponding 3d points
+      const SMDS_PositionPtr Pos1 = n1->GetPosition();
+      const SMDS_PositionPtr Pos2 = n2->GetPosition();
+      int faceID = -1;
+      if( Pos1->GetTypeOfPosition()==SMDS_TOP_FACE ) {
+        faceID = Pos1->GetShapeId();
+      }
+      else if( Pos2->GetTypeOfPosition()==SMDS_TOP_FACE ) {
+        faceID = Pos2->GetShapeId();
+      }
+      if(faceID>-1) {
+        TopoDS_Face F = TopoDS::Face(meshDS->IndexToShape(faceID));
+        gp_XY p1 = GetNodeUV(F,n1);
+        gp_XY p2 = GetNodeUV(F,n2);
+        double u = (p1.X()+p2.X())/2.;
+        double v = (p1.Y()+p2.Y())/2.;
+        Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+        gp_Pnt P = S->Value(u, v);
+        n12 = meshDS->AddNode(P.X(), P.Y(), P.Z());
+        meshDS->SetNodeOnFace(n12, faceID, u, v);
+        myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
+        return n12;
+      }
+    }
+    // 3d variant
+    double x = ( n1->X() + n2->X() )/2.;
+    double y = ( n1->Y() + n2->Y() )/2.;
+    double z = ( n1->Z() + n2->Z() )/2.;
+    n12 = meshDS->AddNode(x,y,z);
+    meshDS->SetNodeInVolume(n12, myShapeID);
+    myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
+    return n12;
+  }
+}
+
+
+//=======================================================================
+//function : AddFace
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for creation quadratic triangle
+ */
+SMDS_MeshFace* StdMeshers_Helper::AddFace(const SMDS_MeshNode* n1,
+                                          const SMDS_MeshNode* n2,
+                                          const SMDS_MeshNode* n3)
+{
+  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  if(!myCreateQuadratic) {
+    return  meshDS->AddFace(n1, n2, n3);
+  }
+
+  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,false);
+  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,false);
+  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,false);
+
+  return  meshDS->AddFace(n1, n2, n3, n12, n23, n31);
+}
+
+
+//=======================================================================
+//function : AddFace
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for creation quadratic quadrangle
+ */
+SMDS_MeshFace* StdMeshers_Helper::AddFace(const SMDS_MeshNode* n1,
+                                          const SMDS_MeshNode* n2,
+                                          const SMDS_MeshNode* n3,
+                                          const SMDS_MeshNode* n4)
+{
+  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  if(!myCreateQuadratic) {
+    return  meshDS->AddFace(n1, n2, n3, n4);
+  }
+
+  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,false);
+  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,false);
+  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,false);
+  const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,false);
+
+  return  meshDS->AddFace(n1, n2, n3, n4, n12, n23, n34, n41);
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for creation quadratic volume
+ */
+SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1,
+                                              const SMDS_MeshNode* n2,
+                                              const SMDS_MeshNode* n3,
+                                              const SMDS_MeshNode* n4,
+                                              const SMDS_MeshNode* n5,
+                                              const SMDS_MeshNode* n6)
+{
+  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  if(!myCreateQuadratic) {
+    return meshDS->AddVolume(n1, n2, n3, n4, n5, n6);
+  }
+
+  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true);
+  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true);
+  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,true);
+
+  const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,true);
+  const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,true);
+  const SMDS_MeshNode* n64 = GetMediumNode(n6,n4,true);
+
+  const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,true);
+  const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,true);
+  const SMDS_MeshNode* n36 = GetMediumNode(n3,n6,true);
+
+  return meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
+                           n12, n23, n31, n45, n56, n64, n14, n25, n36);
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for creation quadratic volume
+ */
+SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1,
+                                              const SMDS_MeshNode* n2,
+                                              const SMDS_MeshNode* n3,
+                                              const SMDS_MeshNode* n4)
+{
+  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  if(!myCreateQuadratic) {
+    return meshDS->AddVolume(n1, n2, n3, n4);
+  }
+
+  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true);
+  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true);
+  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,true);
+
+  const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,true);
+  const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,true);
+  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,true);
+
+  return meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34);
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  : 
+//=======================================================================
+/*!
+ * Special function for creation quadratic volume
+ */
+SMDS_MeshVolume* StdMeshers_Helper::AddVolume(const SMDS_MeshNode* n1,
+                                              const SMDS_MeshNode* n2,
+                                              const SMDS_MeshNode* n3,
+                                              const SMDS_MeshNode* n4,
+                                              const SMDS_MeshNode* n5,
+                                              const SMDS_MeshNode* n6,
+                                              const SMDS_MeshNode* n7,
+                                              const SMDS_MeshNode* n8)
+{
+  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  if(!myCreateQuadratic) {
+    return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
+  }
+
+  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,true);
+  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,true);
+  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,true);
+  const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,true);
+
+  const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,true);
+  const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,true);
+  const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,true);
+  const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,true);
+
+  const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,true);
+  const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,true);
+  const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,true);
+  const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,true);
+
+  return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8,
+                           n12, n23, n34, n41, n56, n67,
+                           n78, n85, n15, n26, n37, n48);
+}
+
+
diff --git a/src/StdMeshers/StdMeshers_Helper.hxx b/src/StdMeshers/StdMeshers_Helper.hxx
new file mode 100644 (file)
index 0000000..33c1853
--- /dev/null
@@ -0,0 +1,149 @@
+// File:      StdMeshers_Helper.hxx
+// Created:   15.02.06 14:48:09
+// Author:    Sergey KUUL
+// Copyright: Open CASCADE 2006
+
+
+#ifndef StdMeshers_Helper_HeaderFile
+#define StdMeshers_Helper_HeaderFile
+
+#include <SMESH_Mesh.hxx>
+#include <TopoDS_Shape.hxx>
+#include <SMDS_MeshNode.hxx>
+#include <TopoDS_Face.hxx>
+#include <gp_XY.hxx>
+
+#include <map>
+
+typedef pair<const SMDS_MeshNode*, const SMDS_MeshNode*> NLink;
+typedef map<NLink, const SMDS_MeshNode*> NLinkNodeMap;
+typedef map<NLink, const SMDS_MeshNode*>::iterator ItNLinkNode;
+
+///  Class StdMeshers_Helper
+//
+
+class StdMeshers_Helper 
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /// Empty constructor
+  StdMeshers_Helper(SMESH_Mesh& theMesh)
+    { myMesh=(void *)&theMesh; myCreateQuadratic = false; }
+
+  SMESH_Mesh* GetMesh() const
+    { return (SMESH_Mesh*)myMesh; }
+    
+  /// Copy constructor
+  //Standard_EXPORT StdMeshers_Helper (const StdMeshers_Helper& theOther);
+
+  /// Destructor
+  //Standard_EXPORT virtual ~StdMeshers_Helper ();
+
+  /**
+   * Check submesh for given shape
+   * If QuadMode is true: check if all elements on this shape
+   * are quadratic, if yes => set true to myCreateQuadratic 
+   * (default value is false). Also fill myNLinkNodeMap
+   * Returns myCreateQuadratic
+   */
+  bool IsQuadraticSubMesh(const TopoDS_Shape& aSh, const bool QuadMode);
+
+  /**
+   * Returns true if given node is medium
+   */
+  bool IsMedium(const SMDS_MeshNode* n);
+
+  /**
+   * Auxilary function for filling myNLinkNodeMap
+   */
+  void AddNLinkNode(const SMDS_MeshNode* n1,
+                    const SMDS_MeshNode* n2,
+                    const SMDS_MeshNode* n12);
+
+  /**
+   * Auxilary function for filling myNLinkNodeMap
+   */
+  void AddNLinkNodeMap(const NLinkNodeMap& aMap)
+    { myNLinkNodeMap.insert(aMap.begin(), aMap.end()); }
+
+  /**
+   * Returns myNLinkNodeMap
+   */
+  const NLinkNodeMap& GetNLinkNodeMap() { return myNLinkNodeMap; }
+
+  /**
+   * Auxilary function for GetMediumNode()
+   */
+  gp_XY GetNodeUV(const TopoDS_Face& F,
+                  const SMDS_MeshNode* n);
+
+  /**
+   * Special function for search or creation medium node
+   */
+  const SMDS_MeshNode* GetMediumNode(const SMDS_MeshNode* n1,
+                                     const SMDS_MeshNode* n2,
+                                     const bool force3d);
+  /**
+   * Special function for creation quadratic triangle
+   */
+  SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1,
+                         const SMDS_MeshNode* n2,
+                         const SMDS_MeshNode* n3);
+
+  /**
+   * Special function for creation quadratic quadrangle
+   */
+  SMDS_MeshFace* AddFace(const SMDS_MeshNode* n1,
+                         const SMDS_MeshNode* n2,
+                         const SMDS_MeshNode* n3,
+                         const SMDS_MeshNode* n4);
+
+  /**
+   * Special function for creation quadratic tetraahedron
+   */
+  SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
+                             const SMDS_MeshNode* n2,
+                             const SMDS_MeshNode* n3,
+                             const SMDS_MeshNode* n4);
+
+  /**
+   * Special function for creation quadratic pentahedron
+   */
+  SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
+                             const SMDS_MeshNode* n2,
+                             const SMDS_MeshNode* n3,
+                             const SMDS_MeshNode* n4,
+                             const SMDS_MeshNode* n5,
+                             const SMDS_MeshNode* n6);
+
+  /**
+   * Special function for creation quadratic hexahedron
+   */
+  SMDS_MeshVolume* AddVolume(const SMDS_MeshNode* n1,
+                             const SMDS_MeshNode* n2,
+                             const SMDS_MeshNode* n3,
+                             const SMDS_MeshNode* n4,
+                             const SMDS_MeshNode* n5,
+                             const SMDS_MeshNode* n6,
+                             const SMDS_MeshNode* n7,
+                             const SMDS_MeshNode* n8);
+
+
+
+ private:
+
+  void* myMesh;
+
+  int myShapeID;
+
+  // Key for creation quadratic faces
+  bool myCreateQuadratic;
+
+  // special map for using during creation quadratic faces
+  NLinkNodeMap myNLinkNodeMap;
+
+};
+
+
+#endif
index a3ed4f11a7142cca9be57bc944b2e49de2af9d57..30384f31d9e65df97b4081582010e06a9637f9ca 100644 (file)
@@ -45,6 +45,7 @@ using namespace std;
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
 
 #include <BRep_Tool.hxx>
 #include <Geom_Surface.hxx>
@@ -146,6 +147,7 @@ static bool findIJ (const SMDS_MeshNode* node, const FaceQuadStruct * quad, int&
   return true;
 }
 
+
 //=============================================================================
 /*!
  * Hexahedron mesh on hexaedron like form
@@ -163,534 +165,529 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
        const TopoDS_Shape & aShape)throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-       MESSAGE("StdMeshers_Hexa_3D::Compute");
-       //bool isOk = false;
-       SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
-       //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
-       //const SMESHDS_SubMesh *& subMeshDS = theSubMesh->GetSubMeshDS();
-
-       // 0.  - shape and face mesh verification
-       // 0.1 - shape must be a solid (or a shell) with 6 faces
-       //MESSAGE("---");
-
-       vector < SMESH_subMesh * >meshFaces;
-       for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next())
-       {
-               SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
-               ASSERT(aSubMesh);
-               meshFaces.push_back(aSubMesh);
-       }
-       if (meshFaces.size() != 6)
-       {
-               SCRUTE(meshFaces.size());
-//             ASSERT(0);
-               return false;
-       }
-
-       // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges)
-       //MESSAGE("---");
-
-       for (int i = 0; i < 6; i++)
-       {
-         TopoDS_Shape aFace = meshFaces[i]->GetSubShape();
-         SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace);
-         string algoName = algo->GetName();
-          bool isAllQuad = false;
-         if (algoName == "Quadrangle_2D") {
-            SMESHDS_SubMesh * sm = meshDS->MeshElements( aFace );
-            if ( sm ) {
-              isAllQuad = true;
-              SMDS_ElemIteratorPtr eIt = sm->GetElements();
-              while ( isAllQuad && eIt->more() )
-                isAllQuad = ( eIt->next()->NbNodes() == 4 );
-            }
-          }
-          if ( ! isAllQuad ) {
-           //modified by NIZNHY-PKV Wed Nov 17 15:31:37 2004 f
-            bool bIsOk;
-            //
-            bIsOk=ComputePentahedralMesh(aMesh, aShape);
-            if (bIsOk) {
-              return true;
-            }
-           //modified by NIZNHY-PKV Wed Nov 17 15:31:42 2004 t
-           SCRUTE(algoName);
-           //                  ASSERT(0);
-           return false;
-         }
-         StdMeshers_Quadrangle_2D *quadAlgo =
-           dynamic_cast < StdMeshers_Quadrangle_2D * >(algo);
-         ASSERT(quadAlgo);
-         try
-           {
-             _quads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace);
-             // *** to delete after usage
-           }
-         catch(SALOME_Exception & S_ex)
-           {
-             // *** delete _quads
-             // *** throw exception
-             //                        ASSERT(0);
-             return false;
-           }
-
-         // 0.2.1 - number of points on the opposite edges must be the same
-         if (_quads[i]->nbPts[0] != _quads[i]->nbPts[2] ||
-             _quads[i]->nbPts[1] != _quads[i]->nbPts[3])
-           {
-             MESSAGE("different number of points on the opposite edges of face " << i);
-             //                  ASSERT(0);
-             return false;
-           }
-       }
-
-       // 1.  - identify faces and vertices of the "cube"
-       // 1.1 - ancestor maps vertex->edges in the cube
-       //MESSAGE("---");
-
-       TopTools_IndexedDataMapOfShapeListOfShape MS;
-       TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS);
-
-       // 1.2 - first face is choosen as face Y=0 of the unit cube
-       //MESSAGE("---");
-
-       const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape();
-       const TopoDS_Face & F = TopoDS::Face(aFace);
-
-       // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001
-       //MESSAGE("---");
-
-       int i = 0;
-       TopoDS_Edge E = _quads[0]->edge[i];     //edge will be Y=0,Z=0 on unit cube
-       double f, l;
-       Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
-       TopoDS_Vertex VFirst, VLast;
-       TopExp::Vertices(E, VFirst, VLast);     // corresponds to f and l
-       bool isForward =
-               (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
+  MESSAGE("StdMeshers_Hexa_3D::Compute");
+  //bool isOk = false;
+  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+  //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
+  //const SMESHDS_SubMesh *& subMeshDS = theSubMesh->GetSubMeshDS();
+  
+  // 0.  - shape and face mesh verification
+  // 0.1 - shape must be a solid (or a shell) with 6 faces
+  //MESSAGE("---");
 
-       if (isForward)
-       {
-               _cube.V000 = VFirst;    // will be (0,0,0) on the unit cube
-               _cube.V100 = VLast;             // will be (1,0,0) on the unit cube
-       }
-       else
-       {
-               _cube.V000 = VLast;
-               _cube.V100 = VFirst;
-       }
+  bool QuadMode = true;
 
-       i = 1;
-       E = _quads[0]->edge[i];
-       C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
-       TopExp::Vertices(E, VFirst, VLast);
-       isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
-       if (isForward)
-               _cube.V101 = VLast;             // will be (1,0,1) on the unit cube
-       else
-               _cube.V101 = VFirst;
+  myTool = new StdMeshers_Helper(aMesh);
+  myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode);
 
-       i = 2;
-       E = _quads[0]->edge[i];
-       C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
-       TopExp::Vertices(E, VFirst, VLast);
-       isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
-       if (isForward)
-               _cube.V001 = VLast;             // will be (0,0,1) on the unit cube
-       else
-               _cube.V001 = VFirst;
+  vector < SMESH_subMesh * >meshFaces;
+  for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
+    SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current());
+    ASSERT(aSubMesh);
+    meshFaces.push_back(aSubMesh);
+  }
+  if (meshFaces.size() != 6) {
+    SCRUTE(meshFaces.size());
+//             ASSERT(0);
+    return false;
+  }
 
-       // 1.4 - find edge X=0, Z=0 (ancestor of V000 not in face Y=0)
-       //     - find edge X=1, Z=0 (ancestor of V100 not in face Y=0)
-       //     - find edge X=1, Z=1 (ancestor of V101 not in face Y=0) 
-       //     - find edge X=0, Z=1 (ancestor of V001 not in face Y=0)
-       //MESSAGE("---");
+  // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges)
+  //MESSAGE("---");
+
+  for (int i = 0; i < 6; i++) {
+    TopoDS_Shape aFace = meshFaces[i]->GetSubShape();
+    SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace);
+    string algoName = algo->GetName();
+    bool isAllQuad = false;
+    if (algoName == "Quadrangle_2D") {
+      SMESHDS_SubMesh * sm = meshDS->MeshElements( aFace );
+      if ( sm ) {
+        isAllQuad = true;
+        SMDS_ElemIteratorPtr eIt = sm->GetElements();
+        while ( isAllQuad && eIt->more() ) {
+          const SMDS_MeshElement* elem =  eIt->next();
+          isAllQuad = ( elem->NbNodes()==4 ||(myCreateQuadratic && elem->NbNodes()==8) );
+        }
+      }
+    }
+    if ( ! isAllQuad ) {
+      //modified by NIZNHY-PKV Wed Nov 17 15:31:37 2004 f
+      bool bIsOk;
+      //
+      bIsOk = ComputePentahedralMesh(aMesh, aShape);
+      if (bIsOk) {
+        return true;
+      }
+      //modified by NIZNHY-PKV Wed Nov 17 15:31:42 2004 t
+      SCRUTE(algoName);
+      //                       ASSERT(0);
+      return false;
+    }
+    StdMeshers_Quadrangle_2D *quadAlgo =
+      dynamic_cast < StdMeshers_Quadrangle_2D * >(algo);
+    ASSERT(quadAlgo);
+    try {
+      _quads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace, myCreateQuadratic);
+      // add links created in quadAlgo into myNLinkNodeMap
+//      NLinkNodeMap aMap = quadAlgo->GetNLinkNodeMap();
+//      myNLinkNodeMap.insert(aMap.begin(), aMap.end());
+      myTool->AddNLinkNodeMap(quadAlgo->GetNLinkNodeMap());
+      // *** to delete after usage
+    }
+    catch(SALOME_Exception & S_ex) {
+      // *** delete _quads
+      // *** throw exception
+      //                       ASSERT(0);
+      return false;
+    }
 
-       TopoDS_Edge E_0Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V000, MS);
-       ASSERT(!E_0Y0.IsNull());
+    // 0.2.1 - number of points on the opposite edges must be the same
+    if (_quads[i]->nbPts[0] != _quads[i]->nbPts[2] ||
+        _quads[i]->nbPts[1] != _quads[i]->nbPts[3]) {
+      MESSAGE("different number of points on the opposite edges of face " << i);
+      //                  ASSERT(0);
+      return false;
+    }
+  }
 
-       TopoDS_Edge E_1Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V100, MS);
-       ASSERT(!E_1Y0.IsNull());
+  // 1.  - identify faces and vertices of the "cube"
+  // 1.1 - ancestor maps vertex->edges in the cube
+  //MESSAGE("---");
 
-       TopoDS_Edge E_1Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V101, MS);
-       ASSERT(!E_1Y1.IsNull());
+  TopTools_IndexedDataMapOfShapeListOfShape MS;
+  TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS);
 
-       TopoDS_Edge E_0Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V001, MS);
-       ASSERT(!E_0Y1.IsNull());
+  // 1.2 - first face is choosen as face Y=0 of the unit cube
+  //MESSAGE("---");
 
-       // 1.5 - identify the 4 vertices in face Y=1: V010, V110, V111, V011
-       //MESSAGE("---");
+  const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape();
+  const TopoDS_Face & F = TopoDS::Face(aFace);
 
-       TopExp::Vertices(E_0Y0, VFirst, VLast);
-       if (VFirst.IsSame(_cube.V000))
-               _cube.V010 = VLast;
-       else
-               _cube.V010 = VFirst;
+  // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001
+  //MESSAGE("---");
 
-       TopExp::Vertices(E_1Y0, VFirst, VLast);
-       if (VFirst.IsSame(_cube.V100))
-               _cube.V110 = VLast;
-       else
-               _cube.V110 = VFirst;
+  int i = 0;
+  TopoDS_Edge E = _quads[0]->edge[i];  //edge will be Y=0,Z=0 on unit cube
+  double f, l;
+  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+  TopoDS_Vertex VFirst, VLast;
+  TopExp::Vertices(E, VFirst, VLast);  // corresponds to f and l
+  bool isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
 
-       TopExp::Vertices(E_1Y1, VFirst, VLast);
-       if (VFirst.IsSame(_cube.V101))
-               _cube.V111 = VLast;
-       else
-               _cube.V111 = VFirst;
+  if (isForward) {
+    _cube.V000 = VFirst;       // will be (0,0,0) on the unit cube
+    _cube.V100 = VLast;                // will be (1,0,0) on the unit cube
+  }
+  else {
+    _cube.V000 = VLast;
+    _cube.V100 = VFirst;
+  }
 
-       TopExp::Vertices(E_0Y1, VFirst, VLast);
-       if (VFirst.IsSame(_cube.V001))
-               _cube.V011 = VLast;
-       else
-               _cube.V011 = VFirst;
-
-       // 1.6 - find remaining faces given 4 vertices
-       //MESSAGE("---");
-
-       _indY0 = 0;
-       _cube.quad_Y0 = _quads[_indY0];
-
-       _indY1 = GetFaceIndex(aMesh, aShape, meshFaces,
-               _cube.V010, _cube.V011, _cube.V110, _cube.V111);
-       _cube.quad_Y1 = _quads[_indY1];
-
-       _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces,
-               _cube.V000, _cube.V010, _cube.V100, _cube.V110);
-       _cube.quad_Z0 = _quads[_indZ0];
-
-       _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces,
-               _cube.V001, _cube.V011, _cube.V101, _cube.V111);
-       _cube.quad_Z1 = _quads[_indZ1];
-
-       _indX0 = GetFaceIndex(aMesh, aShape, meshFaces,
-               _cube.V000, _cube.V001, _cube.V010, _cube.V011);
-       _cube.quad_X0 = _quads[_indX0];
-
-       _indX1 = GetFaceIndex(aMesh, aShape, meshFaces,
-               _cube.V100, _cube.V101, _cube.V110, _cube.V111);
-       _cube.quad_X1 = _quads[_indX1];
-
-       //MESSAGE("---");
-
-       // 1.7 - get convertion coefs from face 2D normalized to 3D normalized
-
-       Conv2DStruct cx0;                       // for face X=0
-       Conv2DStruct cx1;                       // for face X=1
-       Conv2DStruct cy0;
-       Conv2DStruct cy1;
-       Conv2DStruct cz0;
-       Conv2DStruct cz1;
-
-       GetConv2DCoefs(*_cube.quad_X0, meshFaces[_indX0]->GetSubShape(),
-               _cube.V000, _cube.V010, _cube.V011, _cube.V001, cx0);
-       GetConv2DCoefs(*_cube.quad_X1, meshFaces[_indX1]->GetSubShape(),
-               _cube.V100, _cube.V110, _cube.V111, _cube.V101, cx1);
-       GetConv2DCoefs(*_cube.quad_Y0, meshFaces[_indY0]->GetSubShape(),
-               _cube.V000, _cube.V100, _cube.V101, _cube.V001, cy0);
-       GetConv2DCoefs(*_cube.quad_Y1, meshFaces[_indY1]->GetSubShape(),
-               _cube.V010, _cube.V110, _cube.V111, _cube.V011, cy1);
-       GetConv2DCoefs(*_cube.quad_Z0, meshFaces[_indZ0]->GetSubShape(),
-               _cube.V000, _cube.V100, _cube.V110, _cube.V010, cz0);
-       GetConv2DCoefs(*_cube.quad_Z1, meshFaces[_indZ1]->GetSubShape(),
-               _cube.V001, _cube.V101, _cube.V111, _cube.V011, cz1);
-
-       // 1.8 - create a 3D structure for normalized values
-
-       //MESSAGE("---");
-        int nbx = _cube.quad_Z0->nbPts[0];
-        if (cz0.a1 == 0.) nbx = _cube.quad_Z0->nbPts[1];
+  i = 1;
+  E = _quads[0]->edge[i];
+  C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+  TopExp::Vertices(E, VFirst, VLast);
+  isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
+  if (isForward)
+    _cube.V101 = VLast;                // will be (1,0,1) on the unit cube
+  else
+    _cube.V101 = VFirst;
+
+  i = 2;
+  E = _quads[0]->edge[i];
+  C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+  TopExp::Vertices(E, VFirst, VLast);
+  isForward = (((l - f) * (_quads[0]->last[i] - _quads[0]->first[i])) > 0);
+  if (isForward)
+    _cube.V001 = VLast;                // will be (0,0,1) on the unit cube
+  else
+    _cube.V001 = VFirst;
+
+  // 1.4 - find edge X=0, Z=0 (ancestor of V000 not in face Y=0)
+  //     - find edge X=1, Z=0 (ancestor of V100 not in face Y=0)
+  //     - find edge X=1, Z=1 (ancestor of V101 not in face Y=0) 
+  //     - find edge X=0, Z=1 (ancestor of V001 not in face Y=0)
+  //MESSAGE("---");
+
+  TopoDS_Edge E_0Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V000, MS);
+  ASSERT(!E_0Y0.IsNull());
+
+  TopoDS_Edge E_1Y0 = EdgeNotInFace(aMesh, aShape, F, _cube.V100, MS);
+  ASSERT(!E_1Y0.IsNull());
+
+  TopoDS_Edge E_1Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V101, MS);
+  ASSERT(!E_1Y1.IsNull());
+
+  TopoDS_Edge E_0Y1 = EdgeNotInFace(aMesh, aShape, F, _cube.V001, MS);
+  ASSERT(!E_0Y1.IsNull());
+
+  // 1.5 - identify the 4 vertices in face Y=1: V010, V110, V111, V011
+  //MESSAGE("---");
+
+  TopExp::Vertices(E_0Y0, VFirst, VLast);
+  if (VFirst.IsSame(_cube.V000))
+    _cube.V010 = VLast;
+  else
+    _cube.V010 = VFirst;
+
+  TopExp::Vertices(E_1Y0, VFirst, VLast);
+  if (VFirst.IsSame(_cube.V100))
+    _cube.V110 = VLast;
+  else
+    _cube.V110 = VFirst;
+
+  TopExp::Vertices(E_1Y1, VFirst, VLast);
+  if (VFirst.IsSame(_cube.V101))
+    _cube.V111 = VLast;
+  else
+    _cube.V111 = VFirst;
+
+  TopExp::Vertices(E_0Y1, VFirst, VLast);
+  if (VFirst.IsSame(_cube.V001))
+    _cube.V011 = VLast;
+  else
+    _cube.V011 = VFirst;
+
+  // 1.6 - find remaining faces given 4 vertices
+  //MESSAGE("---");
+
+  _indY0 = 0;
+  _cube.quad_Y0 = _quads[_indY0];
+
+  _indY1 = GetFaceIndex(aMesh, aShape, meshFaces,
+                        _cube.V010, _cube.V011, _cube.V110, _cube.V111);
+  _cube.quad_Y1 = _quads[_indY1];
+
+  _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces,
+                        _cube.V000, _cube.V010, _cube.V100, _cube.V110);
+  _cube.quad_Z0 = _quads[_indZ0];
+
+  _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces,
+                        _cube.V001, _cube.V011, _cube.V101, _cube.V111);
+  _cube.quad_Z1 = _quads[_indZ1];
+
+  _indX0 = GetFaceIndex(aMesh, aShape, meshFaces,
+                        _cube.V000, _cube.V001, _cube.V010, _cube.V011);
+  _cube.quad_X0 = _quads[_indX0];
+
+  _indX1 = GetFaceIndex(aMesh, aShape, meshFaces,
+                        _cube.V100, _cube.V101, _cube.V110, _cube.V111);
+  _cube.quad_X1 = _quads[_indX1];
+
+  //MESSAGE("---");
+
+  // 1.7 - get convertion coefs from face 2D normalized to 3D normalized
+
+  Conv2DStruct cx0;                    // for face X=0
+  Conv2DStruct cx1;                    // for face X=1
+  Conv2DStruct cy0;
+  Conv2DStruct cy1;
+  Conv2DStruct cz0;
+  Conv2DStruct cz1;
+
+  GetConv2DCoefs(*_cube.quad_X0, meshFaces[_indX0]->GetSubShape(),
+                 _cube.V000, _cube.V010, _cube.V011, _cube.V001, cx0);
+  GetConv2DCoefs(*_cube.quad_X1, meshFaces[_indX1]->GetSubShape(),
+                 _cube.V100, _cube.V110, _cube.V111, _cube.V101, cx1);
+  GetConv2DCoefs(*_cube.quad_Y0, meshFaces[_indY0]->GetSubShape(),
+                 _cube.V000, _cube.V100, _cube.V101, _cube.V001, cy0);
+  GetConv2DCoefs(*_cube.quad_Y1, meshFaces[_indY1]->GetSubShape(),
+                 _cube.V010, _cube.V110, _cube.V111, _cube.V011, cy1);
+  GetConv2DCoefs(*_cube.quad_Z0, meshFaces[_indZ0]->GetSubShape(),
+                 _cube.V000, _cube.V100, _cube.V110, _cube.V010, cz0);
+  GetConv2DCoefs(*_cube.quad_Z1, meshFaces[_indZ1]->GetSubShape(),
+                 _cube.V001, _cube.V101, _cube.V111, _cube.V011, cz1);
+
+  // 1.8 - create a 3D structure for normalized values
+  
+  //MESSAGE("---");
+  int nbx = _cube.quad_Z0->nbPts[0];
+  if (cz0.a1 == 0.) nbx = _cube.quad_Z0->nbPts[1];
  
-        int nby = _cube.quad_X0->nbPts[0];
-        if (cx0.a1 == 0.) nby = _cube.quad_X0->nbPts[1];
+  int nby = _cube.quad_X0->nbPts[0];
+  if (cx0.a1 == 0.) nby = _cube.quad_X0->nbPts[1];
  
-        int nbz = _cube.quad_Y0->nbPts[0];
-        if (cy0.a1 != 0.) nbz = _cube.quad_Y0->nbPts[1];
-
-       int i1, j1, nbxyz = nbx * nby * nbz;
-       Point3DStruct *np = new Point3DStruct[nbxyz];
+  int nbz = _cube.quad_Y0->nbPts[0];
+  if (cy0.a1 != 0.) nbz = _cube.quad_Y0->nbPts[1];
 
-       // 1.9 - store node indexes of faces
+  int i1, j1, nbxyz = nbx * nby * nbz;
+  Point3DStruct *np = new Point3DStruct[nbxyz];
 
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape());
+  // 1.9 - store node indexes of faces
 
-               faceQuadStruct *quad = _cube.quad_X0;
-               int i = 0;                              // j = x/face , k = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape());
 
+    faceQuadStruct *quad = _cube.quad_X0;
+    int i = 0;                         // j = x/face , k = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
 
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
                        
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
-
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic;     // j = x/face
-                               int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc;     // k = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
-
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape());
-
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               faceQuadStruct *quad = _cube.quad_X1;
-               int i = nbx - 1;                // j = x/face , k = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic;    // j = x/face
+        int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc;    // k = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape());
 
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic;     // j = x/face
-                               int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc;     // k = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
 
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape());
+    faceQuadStruct *quad = _cube.quad_X1;
+    int i = nbx - 1;           // j = x/face , k = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
 
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               faceQuadStruct *quad = _cube.quad_Y0;
-               int j = 0;                              // i = x/face , k = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic;    // j = x/face
+        int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc;    // k = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape());
 
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic;     // i = x/face
-                               int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc;     // k = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
 
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape());
+    faceQuadStruct *quad = _cube.quad_Y0;
+    int j = 0;                         // i = x/face , k = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
 
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               faceQuadStruct *quad = _cube.quad_Y1;
-               int j = nby - 1;                // i = x/face , k = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic;    // i = x/face
+        int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc;    // k = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape());
 
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic;     // i = x/face
-                               int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc;     // k = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
 
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape());
+    faceQuadStruct *quad = _cube.quad_Y1;
+    int j = nby - 1;           // i = x/face , k = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
 
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               faceQuadStruct *quad = _cube.quad_Z0;
-               int k = 0;                              // i = x/face , j = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic;    // i = x/face
+        int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc;    // k = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape());
 
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic;     // i = x/face
-                               int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc;     // j = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
 
-       {
-               const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape());
+    faceQuadStruct *quad = _cube.quad_Z0;
+    int k = 0;                         // i = x/face , j = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
 
-               SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               faceQuadStruct *quad = _cube.quad_Z1;
-               int k = nbz - 1;                // i = x/face , j = y/face
-               int nbdown = quad->nbPts[0];
-               int nbright = quad->nbPts[1];
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic;    // i = x/face
+        int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc;    // j = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-               while(itf->more())
-               {
-                       const SMDS_MeshNode * node = itf->next();
-                        findIJ( node, quad, i1, j1 );
-                       int ij1 = j1 * nbdown + i1;
-                       quad->uv_grid[ij1].node = node;
-               }
+  {
+    const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape());
+
+    SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes();
+
+    faceQuadStruct *quad = _cube.quad_Z1;
+    int k = nbz - 1;           // i = x/face , j = y/face
+    int nbdown = quad->nbPts[0];
+    int nbright = quad->nbPts[1];
+    
+    while(itf->more()) {
+      const SMDS_MeshNode * node = itf->next();
+      if(myTool->IsMedium(node))
+        continue;
+      findIJ( node, quad, i1, j1 );
+      int ij1 = j1 * nbdown + i1;
+      quad->uv_grid[ij1].node = node;
+    }
 
-               for (int i1 = 0; i1 < nbdown; i1++)
-                       for (int j1 = 0; j1 < nbright; j1++)
-                       {
-                               int ij1 = j1 * nbdown + i1;
-                               int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic;     // i = x/face
-                               int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc;     // j = y/face
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
-                               np[ijk].node = quad->uv_grid[ij1].node;
-                               //SCRUTE(np[ijk].nodeId);
-                       }
-       }
+    for (int i1 = 0; i1 < nbdown; i1++)
+      for (int j1 = 0; j1 < nbright; j1++) {
+        int ij1 = j1 * nbdown + i1;
+        int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic;    // i = x/face
+        int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc;    // j = y/face
+        int ijk = k * nbx * nby + j * nbx + i;
+        //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk);
+        np[ijk].node = quad->uv_grid[ij1].node;
+        //SCRUTE(np[ijk].nodeId);
+      }
+  }
 
-       // 2.0 - for each node of the cube:
-       //       - get the 8 points 3D = 8 vertices of the cube
-       //       - get the 12 points 3D on the 12 edges of the cube
-       //       - get the 6 points 3D on the 6 faces with their ID
-       //       - compute the point 3D
-       //       - store the point 3D in SMESHDS, store its ID in 3D structure
-
-        int shapeID = meshDS->ShapeToIndex( aShape );
-
-       Pt3 p000, p001, p010, p011, p100, p101, p110, p111;
-       Pt3 px00, px01, px10, px11;
-       Pt3 p0y0, p0y1, p1y0, p1y1;
-       Pt3 p00z, p01z, p10z, p11z;
-       Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz;
-
-       GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS);
-       GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
-       GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS);
-       GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
-       GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS);
-       GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
-       GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS);
-       GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
-
-       for (int i = 1; i < nbx - 1; i++)
-       {
-               for (int j = 1; j < nby - 1; j++)
-               {
-                       for (int k = 1; k < nbz - 1; k++)
-                       {
-                               // *** seulement maillage regulier
-                               // 12 points on edges
-                               GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS);
-                               GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
-                               GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS);
-                               GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
-
-                               GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS);
-
-                               GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS);
-
-                               // 12 points on faces
-                               GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS);
-                               GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS);
-                               GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS);
-                               GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS);
-
-                               int ijk = k * nbx * nby + j * nbx + i;
-                               double x = double (i) / double (nbx - 1);       // *** seulement
-                               double y = double (j) / double (nby - 1);       // *** maillage
-                               double z = double (k) / double (nbz - 1);       // *** regulier
-
-                               Pt3 X;
-                               for (int i = 0; i < 3; i++)
-                               {
-                                       X[i] =
-                                               (1 - x) * p0yz[i] + x * p1yz[i]
-                                               + (1 - y) * px0z[i] + y * px1z[i]
-                                               + (1 - z) * pxy0[i] + z * pxy1[i]
-                                               - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i])
-                                               - x * ((1 - y) * p10z[i] + y * p11z[i])
-                                               - (1 - y) * ((1 - z) * px00[i] + z * px01[i])
-                                               - y * ((1 - z) * px10[i] + z * px11[i])
-                                               - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i])
-                                               - z * ((1 - x) * p0y1[i] + x * p1y1[i])
-                                               + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i])
-                                               + y * ((1 - z) * p010[i] + z * p011[i]))
-                                               + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i])
-                                               + y * ((1 - z) * p110[i] + z * p111[i]));
-                               }
-
-                               SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]);
-                               np[ijk].node = node;
-                                meshDS->SetNodeInVolume(node, shapeID);
-                       }
-               }
-       }
+  // 2.0 - for each node of the cube:
+  //       - get the 8 points 3D = 8 vertices of the cube
+  //       - get the 12 points 3D on the 12 edges of the cube
+  //       - get the 6 points 3D on the 6 faces with their ID
+  //       - compute the point 3D
+  //       - store the point 3D in SMESHDS, store its ID in 3D structure
+
+  int shapeID = meshDS->ShapeToIndex( aShape );
+
+  Pt3 p000, p001, p010, p011, p100, p101, p110, p111;
+  Pt3 px00, px01, px10, px11;
+  Pt3 p0y0, p0y1, p1y0, p1y1;
+  Pt3 p00z, p01z, p10z, p11z;
+  Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz;
+
+  GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS);
+  GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
+  GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS);
+  GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
+  GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS);
+  GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
+  GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS);
+  GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
+
+  for (int i = 1; i < nbx - 1; i++) {
+    for (int j = 1; j < nby - 1; j++) {
+      for (int k = 1; k < nbz - 1; k++) {
+        // *** seulement maillage regulier
+        // 12 points on edges
+        GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS);
+        GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS);
+        GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS);
+        GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS);
+
+        GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS);
+        GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS);
+        GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS);
+        GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS);
+
+        GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS);
+
+        // 12 points on faces
+        GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS);
+        GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS);
+        GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS);
+        GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS);
+
+        int ijk = k * nbx * nby + j * nbx + i;
+        double x = double (i) / double (nbx - 1);      // *** seulement
+        double y = double (j) / double (nby - 1);      // *** maillage
+        double z = double (k) / double (nbz - 1);      // *** regulier
+
+        Pt3 X;
+        for (int i = 0; i < 3; i++) {
+          X[i] = (1 - x) * p0yz[i] + x * p1yz[i]
+                 + (1 - y) * px0z[i] + y * px1z[i]
+                 + (1 - z) * pxy0[i] + z * pxy1[i]
+                 - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i])
+                 - x * ((1 - y) * p10z[i] + y * p11z[i])
+                 - (1 - y) * ((1 - z) * px00[i] + z * px01[i])
+                 - y * ((1 - z) * px10[i] + z * px11[i])
+                 - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i])
+                 - z * ((1 - x) * p0y1[i] + x * p1y1[i])
+                 + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i])
+                 + y * ((1 - z) * p010[i] + z * p011[i]))
+                 + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i])
+                 + y * ((1 - z) * p110[i] + z * p111[i]));
+        }
+
+        SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]);
+        np[ijk].node = node;
+        meshDS->SetNodeInVolume(node, shapeID);
+      }
+    }
+  }
 
   // find orientation of furute volumes according to MED convention
   vector< bool > forward( nbx * nby );
   SMDS_VolumeTool vTool;
-  for (int i = 0; i < nbx - 1; i++)
-    for (int j = 0; j < nby - 1; j++)
-    {
+  for (int i = 0; i < nbx - 1; i++) {
+    for (int j = 0; j < nby - 1; j++) {
       int n1 = j * nbx + i;
       int n2 = j * nbx + i + 1;
       int n3 = (j + 1) * nbx + i + 1;
@@ -705,51 +702,53 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
       vTool.Set( &tmpVol );
       forward[ n1 ] = vTool.IsForward();
     }
+  }
 
-       //2.1 - for each node of the cube (less 3 *1 Faces):
-       //      - store hexahedron in SMESHDS
-       MESSAGE("Storing hexahedron into the DS");
-       for (int i = 0; i < nbx - 1; i++)
-               for (int j = 0; j < nby - 1; j++)
-                {
-                        bool isForw = forward.at( j * nbx + i );
-                       for (int k = 0; k < nbz - 1; k++)
-                       {
-                               int n1 = k * nbx * nby + j * nbx + i;
-                               int n2 = k * nbx * nby + j * nbx + i + 1;
-                               int n3 = k * nbx * nby + (j + 1) * nbx + i + 1;
-                               int n4 = k * nbx * nby + (j + 1) * nbx + i;
-                               int n5 = (k + 1) * nbx * nby + j * nbx + i;
-                               int n6 = (k + 1) * nbx * nby + j * nbx + i + 1;
-                               int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1;
-                               int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i;
-
-                               SMDS_MeshVolume * elt;
-                                if ( isForw )
-                                  elt = meshDS->AddVolume(np[n1].node,
-                                                          np[n2].node,
-                                                          np[n3].node,
-                                                          np[n4].node,
-                                                          np[n5].node,
-                                                          np[n6].node,
-                                                          np[n7].node,
-                                                          np[n8].node);
-                                else
-                                  elt = meshDS->AddVolume(np[n1].node,
-                                                          np[n4].node,
-                                                          np[n3].node,
-                                                          np[n2].node,
-                                                          np[n5].node,
-                                                          np[n8].node,
-                                                          np[n7].node,
-                                                          np[n6].node);
-
-                                meshDS->SetMeshElementOnShape(elt, shapeID);
-                              }
-                      }
+  //2.1 - for each node of the cube (less 3 *1 Faces):
+  //      - store hexahedron in SMESHDS
+  MESSAGE("Storing hexahedron into the DS");
+  for (int i = 0; i < nbx - 1; i++) {
+    for (int j = 0; j < nby - 1; j++) {
+      bool isForw = forward.at( j * nbx + i );
+      for (int k = 0; k < nbz - 1; k++) {
+        int n1 = k * nbx * nby + j * nbx + i;
+        int n2 = k * nbx * nby + j * nbx + i + 1;
+        int n3 = k * nbx * nby + (j + 1) * nbx + i + 1;
+        int n4 = k * nbx * nby + (j + 1) * nbx + i;
+        int n5 = (k + 1) * nbx * nby + j * nbx + i;
+        int n6 = (k + 1) * nbx * nby + j * nbx + i + 1;
+        int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1;
+        int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i;
+
+        SMDS_MeshVolume * elt;
+        if ( isForw ) {
+          //elt = meshDS->AddVolume(np[n1].node, np[n2].node,
+          //                        np[n3].node, np[n4].node,
+          //                        np[n5].node, np[n6].node,
+          //                        np[n7].node, np[n8].node);
+          elt = myTool->AddVolume(np[n1].node, np[n2].node,
+                                  np[n3].node, np[n4].node,
+                                  np[n5].node, np[n6].node,
+                                  np[n7].node, np[n8].node);
+        }
+        else {
+          //elt = meshDS->AddVolume(np[n1].node, np[n4].node,
+          //                        np[n3].node, np[n2].node,
+          //                        np[n5].node, np[n8].node,
+          //                        np[n7].node, np[n6].node);
+          elt = myTool->AddVolume(np[n1].node, np[n4].node,
+                                  np[n3].node, np[n2].node,
+                                  np[n5].node, np[n8].node,
+                                  np[n7].node, np[n6].node);
+        }
+        
+        meshDS->SetMeshElementOnShape(elt, shapeID);
+      }
+    }
+  }
   if ( np ) delete [] np;
-       //MESSAGE("End of StdMeshers_Hexa_3D::Compute()");
-       return true;
+  //MESSAGE("End of StdMeshers_Hexa_3D::Compute()");
+  return true;
 }
 
 //=============================================================================
@@ -1066,3 +1065,4 @@ bool ComputePentahedralMesh(SMESH_Mesh & aMesh,   const TopoDS_Shape & aShape)
   return bOK;
 }
 
+
index a9e20459c8ac94c51bea1ce88d10378acb8a1b63..dd733e55c3db97a26ac327d879c6ad4c03957e7b 100644 (file)
@@ -35,6 +35,8 @@
 #include "StdMeshers_Quadrangle_2D.hxx"
 #include "Utils_SALOME_Exception.hxx"
 
+#include "StdMeshers_Helper.hxx"
+
 typedef struct point3Dstruct
 {
        const SMDS_MeshNode * node;
@@ -135,6 +137,9 @@ protected:
   int _indY1;
   int _indZ0;
   int _indZ1;
+
+  bool myCreateQuadratic;
+  StdMeshers_Helper* myTool; // toll for working with quadratic elements
 };
 
 #endif
index ed166fc036f14a988740b37ea6c21b42c80804d7..22b1702b2e19dfd09d0f360d9fd2c963faf1d8e4 100644 (file)
@@ -184,73 +184,76 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis
 
 bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
 {
-       MESSAGE("StdMeshers_MEFISTO_2D::Compute");
+  MESSAGE("StdMeshers_MEFISTO_2D::Compute");
 
-       if (_hypLengthFromEdges)
-               _edgeLength = ComputeEdgeElementLength(aMesh, aShape);
+  if (_hypLengthFromEdges)
+    _edgeLength = ComputeEdgeElementLength(aMesh, aShape);
+  
+  bool isOk = false;
+  //const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+  //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
 
-       bool isOk = false;
-       //const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
-       //SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
-
-       const TopoDS_Face & FF = TopoDS::Face(aShape);
-       bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
-       TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
-
-       Z nblf;                                         //nombre de lignes fermees (enveloppe en tete)
-       Z *nudslf = NULL;                       //numero du dernier sommet de chaque ligne fermee
-       R2 *uvslf = NULL;
-       Z nbpti = 0;                            //nombre points internes futurs sommets de la triangulation
-       R2 *uvpti = NULL;
-
-       Z nbst;
-       R2 *uvst = NULL;
-       Z nbt;
-       Z *nust = NULL;
-       Z ierr = 0;
-
-       Z nutysu = 1;                           // 1: il existe un fonction areteideale_()
-       // Z  nutysu=0;              // 0: on utilise aretmx
-       R aretmx = _edgeLength;         // longueur max aretes future triangulation
-
-       nblf = NumberOfWires(F);
-
-       nudslf = new Z[1 + nblf];
-       nudslf[0] = 0;
-       int iw = 1;
-       int nbpnt = 0;
-
-       myOuterWire = BRepTools::OuterWire(F);
-       nbpnt += NumberOfPoints(aMesh, myOuterWire);
-        if ( nbpnt < 3 ) // ex: a circle with 2 segments
-          return false;
-       nudslf[iw++] = nbpnt;
+  const TopoDS_Face & FF = TopoDS::Face(aShape);
+  bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
+  TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
 
-       for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
-       {
-               const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
-               if (!myOuterWire.IsSame(W))
-               {
-                       nbpnt += NumberOfPoints(aMesh, W);
-                       nudslf[iw++] = nbpnt;
-               }
-       }
+  Z nblf;                                              //nombre de lignes fermees (enveloppe en tete)
+  Z *nudslf = NULL;                    //numero du dernier sommet de chaque ligne fermee
+  R2 *uvslf = NULL;
+  Z nbpti = 0;                         //nombre points internes futurs sommets de la triangulation
+  R2 *uvpti = NULL;
+  
+  Z nbst;
+  R2 *uvst = NULL;
+  Z nbt;
+  Z *nust = NULL;
+  Z ierr = 0;
+
+  Z nutysu = 1;                                // 1: il existe un fonction areteideale_()
+  // Z  nutysu=0;              // 0: on utilise aretmx
+  R aretmx = _edgeLength;              // longueur max aretes future triangulation
+  
+  nblf = NumberOfWires(F);
+  
+  nudslf = new Z[1 + nblf];
+  nudslf[0] = 0;
+  int iw = 1;
+  int nbpnt = 0;
+
+  bool QuadMode = true;
+
+  myTool = new StdMeshers_Helper(aMesh);
+  myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode);
+
+  myOuterWire = BRepTools::OuterWire(F);
+  nbpnt += NumberOfPoints(aMesh, myOuterWire);
+  if ( nbpnt < 3 ) // ex: a circle with 2 segments
+    return false;
+  nudslf[iw++] = nbpnt;
+
+  for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next()) {
+    const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
+    if (!myOuterWire.IsSame(W)) {
+      nbpnt += NumberOfPoints(aMesh, W);
+      nudslf[iw++] = nbpnt;
+    }
+  }
 
-        // avoid passing same uv points for a vertex common to 2 wires
-        TopTools_IndexedDataMapOfShapeListOfShape VWMap;
-        if ( iw - 1 > 1 ) // nbofWires > 1
-          TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap );
+  // avoid passing same uv points for a vertex common to 2 wires
+  TopTools_IndexedDataMapOfShapeListOfShape VWMap;
+  if ( iw - 1 > 1 ) // nbofWires > 1
+    TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap );
 
-       uvslf = new R2[nudslf[nblf]];
-       int m = 0;
+  uvslf = new R2[nudslf[nblf]];
+  int m = 0;
 
-        double scalex, scaley;
-        ComputeScaleOnFace(aMesh, F, scalex, scaley);
+  double scalex, scaley;
+  ComputeScaleOnFace(aMesh, F, scalex, scaley);
 
-        map<int, const SMDS_MeshNode*> mefistoToDS;    // correspondence mefisto index--> points IDNodes
-       if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m,
-                         mefistoToDS, scalex, scaley, VWMap))
-          return false;
+  map<int, const SMDS_MeshNode*> mefistoToDS;  // correspondence mefisto index--> points IDNodes
+  if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m,
+                   mefistoToDS, scalex, scaley, VWMap) )
+    return false;
 
        for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
        {
@@ -352,7 +355,8 @@ static bool fixCommonVertexUV (gp_Pnt2d &           theUV,
                                const TopoDS_Wire&   theOW,
                                const TopoDS_Face&   theF,
                                const TopTools_IndexedDataMapOfShapeListOfShape & theVWMap,
-                               SMESH_Mesh &         theMesh)
+                               SMESH_Mesh &         theMesh,
+                               bool CreateQuadratic)
 {
   if( theW.IsSame( theOW ) ||
       !theVWMap.Contains( theV )) return false;
@@ -415,10 +419,25 @@ static bool fixCommonVertexUV (gp_Pnt2d &           theUV,
       umin = l;
       umax = f;
     }
-    else
-    {
+    else {
       while ( nIt->more() ) {
         const SMDS_MeshNode* node = nIt->next();
+        if(CreateQuadratic) {
+          // check if node is medium
+          bool IsMedium = false;
+          SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator();
+          while (itn->more()) {
+            const SMDS_MeshElement* elem = itn->next();
+            if ( elem->GetType() != SMDSAbs_Edge )
+              continue;
+            if(elem->IsMediumNode(node)) {
+              IsMedium = true;
+              break;
+            }
+          }
+          if(IsMedium)
+            continue;
+        }
         const SMDS_EdgePosition* epos =
           static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
         double u = epos->GetUParameter();
@@ -486,8 +505,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
 
   TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD));
   BRepTools_WireExplorer wexp(W, F);
-  for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++)
-  {
+  for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++) {
     const TopoDS_Edge & E = wexp.Current();
 
     // --- IDNodes of first and last Vertex
@@ -496,7 +514,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
     TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l
 
     ASSERT(!VFirst.IsNull());
-    SMDS_NodeIteratorPtr lid=
+    SMDS_NodeIteratorPtr lid =
       aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
     if ( !lid->more() ) {
       MESSAGE (" NO NODE BUILT ON VERTEX ");
@@ -505,7 +523,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
     const SMDS_MeshNode* idFirst = lid->next();
 
     ASSERT(!VLast.IsNull());
-    lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
+    lid = aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
     if ( !lid->more() ) {
       MESSAGE (" NO NODE BUILT ON VERTEX ");
       return false;
@@ -514,6 +532,21 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
 
     // --- edge internal IDNodes (relies on good order storage, not checked)
 
+//    if(myCreateQuadratic) {
+      // fill myNLinkNodeMap
+//      SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements();
+//      while(iter->more()) {
+//        const SMDS_MeshElement* elem = iter->next();
+//        SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+//        const SMDS_MeshNode* n1 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//        const SMDS_MeshNode* n2 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//        const SMDS_MeshNode* n3 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//        NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+//        myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3));
+//        myNLinkNodeMap[link] = n3;
+//      }
+//    }
+
     int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
 
     double f, l;
@@ -524,16 +557,41 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
     //bool isForward = (E.Orientation() == TopAbs_FORWARD);
     map<double, const SMDS_MeshNode*> params;
 
-    while(ite->more())
-    {
-      const SMDS_MeshNode * node = ite->next();
-      const SMDS_EdgePosition* epos =
-        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
-      double param = epos->GetUParameter();
-      params[param] = node;
+    if(!myCreateQuadratic) {
+      while(ite->more()) {
+        const SMDS_MeshNode * node = ite->next();
+        const SMDS_EdgePosition* epos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        double param = epos->GetUParameter();
+        params[param] = node;
+      }
     }
-    if ( nbPoints != params.size())
-    {
+    else {
+      nbPoints = nbPoints/2;
+      while(ite->more()) {
+        const SMDS_MeshNode* node = ite->next();
+        // check if node is medium
+        bool IsMedium = false;
+        SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator();
+        while (itn->more()) {
+          const SMDS_MeshElement* elem = itn->next();
+          if ( elem->GetType() != SMDSAbs_Edge )
+            continue;
+          if(elem->IsMediumNode(node)) {
+            IsMedium = true;
+            break;
+          }
+        }
+        if(IsMedium)
+          continue;
+        const SMDS_EdgePosition* epos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        double param = epos->GetUParameter();
+        params[param] = node;
+      }
+    }
+
+    if ( nbPoints != params.size()) {
       MESSAGE( "BAD NODE ON EDGE POSITIONS" );
       return false;
     }
@@ -542,10 +600,9 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
 
     // --- load 2D values into MEFISTO structure,
     //     add IDNodes in mefistoToDS map
-    if (E.Orientation() == TopAbs_FORWARD)
-    {
+    if (E.Orientation() == TopAbs_FORWARD) {
       gp_Pnt2d p = C2d->Value(f).XY().Multiplied( scale );       // first point = Vertex Forward
-      if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh ))
+      if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh, myCreateQuadratic ))
         myNodesOnCommonV.push_back( idFirst );
       uvslf[m].x = p.X();
       uvslf[m].y = p.Y();
@@ -554,8 +611,7 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
       //MESSAGE("__ f "<<f<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
       m++;
       map<double, const SMDS_MeshNode*>::iterator itp = params.begin();
-      for (int i = 1; i <= nbPoints; i++)       // nbPoints internal
-      {
+      for (int i = 1; i <= nbPoints; i++) {  // nbPoints internal
         double param = (*itp).first;
         gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale );
         uvslf[m].x = p.X();
@@ -567,10 +623,9 @@ bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
         itp++;
       }
     }
-    else
-    {
+    else {
       gp_Pnt2d p = C2d->Value(l).XY().Multiplied( scale );       // last point = Vertex Reversed
-      if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh ))
+      if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh, myCreateQuadratic ))
         myNodesOnCommonV.push_back( idLast );
       uvslf[m].x = p.X();
       uvslf[m].y = p.Y();
@@ -758,9 +813,11 @@ void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh,
 
     SMDS_MeshElement * elt;
     if (triangleIsWellOriented)
-      elt = meshDS->AddFace(n1, n2, n3);
+      //elt = meshDS->AddFace(n1, n2, n3);
+      elt = myTool->AddFace(n1, n2, n3);
     else
-      elt = meshDS->AddFace(n1, n3, n2);
+      //elt = meshDS->AddFace(n1, n3, n2);
+      elt = myTool->AddFace(n1, n3, n2);
 
     meshDS->SetMeshElementOnShape(elt, faceID);
     m++;
index fac85f07d0a725d090b3f303291011d10e5a4529..180ceb7605e81a058977b234115f21e33d786655 100644 (file)
@@ -33,6 +33,8 @@
 #include "SMESH_2D_Algo.hxx"
 #include <TopoDS_Wire.hxx>
 
+#include "StdMeshers_Helper.hxx"
+
 class SMDS_MeshNode;
 class TopTools_IndexedDataMapOfShapeListOfShape;
 class TopoDS_Face;
@@ -95,6 +97,8 @@ protected:
 
   TopoDS_Wire myOuterWire;
   std::list<const SMDS_MeshNode*> myNodesOnCommonV;
+
+  StdMeshers_Helper* myTool; // toll for working with quadratic elements
 };
 
 #endif
index ad6ebc83198609b882539342061257d2b33e4f5d..6c432f70407a90744027127377e57cb939e48e17 100644 (file)
@@ -51,6 +51,9 @@
 #include <TopoDS_Shell.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <gp_Pnt.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <TopTools_MapOfShape.hxx>
 
 #include <stdio.h>
 #include <algorithm>
@@ -71,6 +74,8 @@ StdMeshers_Penta_3D::StdMeshers_Penta_3D()
   myWallNodesMaps.resize( SMESH_Block::NbFaces() );
   myShapeXYZ.resize( SMESH_Block::NbSubShapes() );
 }
+
+
 //=======================================================================
 //function : Compute
 //purpose  : 
@@ -91,9 +96,20 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh,
   if (myErrorStatus){
     return bOK;
   }
+
+  bool QuadMode = true;
+
+  myTool = new StdMeshers_Helper(aMesh);
+  myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode);
+
   //
   MakeBlock();
-    if (myErrorStatus){
+  if (myErrorStatus){
+    return bOK;
+  }
+  //
+  ClearMeshOnFxy1();
+  if (myErrorStatus) {
     return bOK;
   }
   //
@@ -104,11 +120,6 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh,
   //
   MakeConnectingMap();
   //
-  ClearMeshOnFxy1();
-  if (myErrorStatus) {
-    return bOK;
-  }
-  //
   MakeMeshOnFxy1();
   if (myErrorStatus) {
     return bOK;
@@ -118,6 +129,7 @@ bool StdMeshers_Penta_3D::Compute(SMESH_Mesh& aMesh,
   //
   return !bOK;
 }
+
 //=======================================================================
 //function : MakeNodes
 //purpose  : 
@@ -144,12 +156,24 @@ void StdMeshers_Penta_3D::MakeNodes()
   // 1.1 Horizontal size
   myJSize=0;
   for (i=0; i<aNbSIDs; ++i) {
-    const TopoDS_Shape& aS=myBlock.Shape(aSIDs[i]);
+    const TopoDS_Shape& aS = myBlock.Shape(aSIDs[i]);
     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aS);
     ASSERT(aSubMesh);
-    SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS();
-    iNbN=aSM->NbNodes();
-    myJSize+=iNbN;
+    SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
+    if(!myCreateQuadratic) {
+      iNbN = aSM->NbNodes();
+    }
+    else {
+      iNbN = 0;
+      SMDS_NodeIteratorPtr itn = aSM->GetNodes();
+      while(itn->more()) {
+        const SMDS_MeshNode* aNode = itn->next();
+        if(myTool->IsMedium(aNode))
+          continue;
+        iNbN++;
+      }
+    }
+    myJSize += iNbN;
   }
   //printf("***  Horizontal: number of nodes summary=%d\n", myJSize);
   //
@@ -159,9 +183,21 @@ void StdMeshers_Penta_3D::MakeNodes()
     const TopoDS_Shape& aS=myBlock.Shape(SMESH_Block::ID_E00z);
     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aS);
     ASSERT(aSubMesh);
-    SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS();
-    iNbN=aSM->NbNodes();
-    myISize+=iNbN;
+    SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
+    if(!myCreateQuadratic) {
+      iNbN = aSM->NbNodes();
+    }
+    else {
+      iNbN = 0;
+      SMDS_NodeIteratorPtr itn = aSM->GetNodes();
+      while(itn->more()) {
+        const SMDS_MeshNode* aNode = itn->next();
+        if(myTool->IsMedium(aNode))
+          continue;
+        iNbN++;
+      }
+    }
+    myISize += iNbN;
   }
   //printf("***  Vertical: number of nodes on edges and vertices=%d\n", myISize);
   //
@@ -177,18 +213,19 @@ void StdMeshers_Penta_3D::MakeNodes()
   // vertices
   for (k=0; k<aNbSIDs; ++k) {
     aSID=aSIDs[k];
-    const TopoDS_Shape& aS=myBlock.Shape(aSID);
-    SMDS_NodeIteratorPtr ite =pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes();
+    const TopoDS_Shape& aS = myBlock.Shape(aSID);
+    SMDS_NodeIteratorPtr ite = pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes();
     while(ite->more()) {
       const SMDS_MeshNode* aNode = ite->next();
+      if(myTool->IsMedium(aNode))
+        continue;
       aNodeID=aNode->GetID();
       //
       aTNode.SetNode(aNode);
       aTNode.SetShapeSupportID(aSID);
       aTNode.SetBaseNodeID(aNodeID);
       //
-      if ( SMESH_Block::IsEdgeID (aSID))
-      {
+      if ( SMESH_Block::IsEdgeID (aSID)) {
         const SMDS_EdgePosition* epos =
           static_cast<const SMDS_EdgePosition*>(aNode->GetPosition().get());
         myBlock.ComputeParameters( epos->GetUParameter(), aS, aCoords );
@@ -200,7 +237,7 @@ void StdMeshers_Penta_3D::MakeNodes()
         aP3D.SetCoord(aX, aY, aZ);
         myBlock.ComputeParameters(aP3D, aS, aCoords);
       }
-      iErr=myBlock.ErrorStatus();
+      iErr = myBlock.ErrorStatus();
       if (iErr) {
         MESSAGE("StdMeshers_Penta_3D::MakeNodes()," <<
                 "SMESHBlock: ComputeParameters operation failed");
@@ -325,8 +362,7 @@ void StdMeshers_Penta_3D::MakeNodes()
 
   // 3.3 set XYZ of vertices, and initialize of the rest
   SMESHDS_Mesh* aMesh = GetMesh()->GetMeshDS();
-  for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id )
-  {
+  for ( int id = SMESH_Block::ID_V000; id < SMESH_Block::ID_Shell; ++id ) {
     if ( SMESH_Block::IsVertexID( id )) {
       TopoDS_Shape V = myBlock.Shape( id );
       SMESHDS_SubMesh* sm = aMesh->MeshElements( V );
@@ -344,23 +380,46 @@ void StdMeshers_Penta_3D::MakeNodes()
   SMESH_Block::TShapeID aSSID, aBNSSID;
   StdMeshers_TNode aTN;
   //
-  for (j=0; j<myJSize; ++j)
-  {
+
+  // create top face and find UV for it's corners
+  const TopoDS_Face& TopFace = TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy1));
+  SMESHDS_Mesh* meshDS = pMesh->GetMeshDS();
+  int topfaceID = meshDS->ShapeToIndex(TopFace);
+  const TopoDS_Vertex& v001 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V001));
+  SMDS_NodeIteratorPtr itn = pMesh->GetSubMeshContaining(v001)->GetSubMeshDS()->GetNodes();
+  const SMDS_MeshNode* N = itn->next();
+  gp_XY UV001 = myTool->GetNodeUV(TopFace,N);
+  const TopoDS_Vertex& v101 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V101));
+  itn = pMesh->GetSubMeshContaining(v101)->GetSubMeshDS()->GetNodes();
+  N = itn->next();
+  gp_XY UV101 = myTool->GetNodeUV(TopFace,N);
+  const TopoDS_Vertex& v011 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V011));
+  itn = pMesh->GetSubMeshContaining(v011)->GetSubMeshDS()->GetNodes();
+  N = itn->next();
+  gp_XY UV011 = myTool->GetNodeUV(TopFace,N);
+  const TopoDS_Vertex& v111 = TopoDS::Vertex(myBlock.Shape(SMESH_Block::ID_V111));
+  itn = pMesh->GetSubMeshContaining(v111)->GetSubMeshDS()->GetNodes();
+  N = itn->next();
+  gp_XY UV111 = myTool->GetNodeUV(TopFace,N);
+
+  for (j=0; j<myJSize; ++j) {
     // base node info
-    const StdMeshers_TNode& aBN=myTNodes[j];
-    aBNSSID=(SMESH_Block::TShapeID)aBN.ShapeSupportID();
-    iBNID=aBN.BaseNodeID();
-    const gp_XYZ& aBNXYZ=aBN.NormCoord();
+    const StdMeshers_TNode& aBN = myTNodes[j];
+    aBNSSID = (SMESH_Block::TShapeID)aBN.ShapeSupportID();
+    iBNID = aBN.BaseNodeID();
+    const gp_XYZ& aBNXYZ = aBN.NormCoord();
     bool createNode = ( aBNSSID == SMESH_Block::ID_Fxy0 );
     //
     // set XYZ on horizontal edges and get node columns of faces:
     // 2 columns for each face, between which a base node is located
     vector<const SMDS_MeshNode*>* nColumns[8];
     double ratio[4]; // base node position between columns [0.-1.]
-    if ( createNode )
-      for ( k = 0; k < 4; ++k )
+    if ( createNode ) {
+      for ( k = 0; k < 4; ++k ) {
         ratio[ k ] = SetHorizEdgeXYZ (aBNXYZ, wallFaceID[ k ],
                                       nColumns[k*2], nColumns[k*2+1]);
+      }
+    }
     //
     // XYZ on the bottom and top faces
     const SMDS_MeshNode* n = aBN.Node();
@@ -368,8 +427,9 @@ void StdMeshers_Penta_3D::MakeNodes()
     myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( 0., 0., 0. );
     //
     // first create or find a top node, then the rest ones in a column
-    for (i=myISize-1; i>0; --i)
-    {
+    for (i=myISize-1; i>0; --i) {
+      bIsUpperLayer = (i==(myISize-1));
+      gp_XY UV_Ex01, UV_Ex11, UV_E0y1, UV_E1y1;
       if ( createNode ) {
         // set XYZ on vertical edges and faces
         for ( k = 0; k < 4; ++k ) {
@@ -377,11 +437,28 @@ void StdMeshers_Penta_3D::MakeNodes()
           myShapeXYZ[ verticEdgeID[ k ] ].SetCoord( n->X(), n->Y(), n->Z() );
           //
           n = (*nColumns[k*2]) [ i ];
+          gp_XY tmp1;
+          if( i==myISize-1 ) {
+            tmp1 = myTool->GetNodeUV(TopFace,n);
+            tmp1 = ( 1. - ratio[ k ]) * tmp1;
+          }
           gp_XYZ xyz( n->X(), n->Y(), n->Z() );
           myShapeXYZ[ wallFaceID[ k ]] = ( 1. - ratio[ k ]) * xyz;
           n = (*nColumns[k*2+1]) [ i ];
           xyz.SetCoord( n->X(), n->Y(), n->Z() );
           myShapeXYZ[ wallFaceID[ k ]] += ratio[ k ] * xyz;
+          if( i==myISize-1 ) {
+            gp_XY tmp2 = myTool->GetNodeUV(TopFace,n);
+            tmp1 +=  ratio[ k ] * tmp2;
+            if( k==0 )
+              UV_Ex01 = tmp1;
+            else if( k==1 )
+              UV_Ex11 = tmp1;
+            else if( k==2 )
+              UV_E0y1 = tmp1;
+            else
+              UV_E1y1 = tmp1;
+          }
         }
       }
       // fill current node info
@@ -395,7 +472,6 @@ void StdMeshers_Penta_3D::MakeNodes()
       aCoords.SetCoord(aX, aY, aZ);
       //
       //   suporting shape ID
-      bIsUpperLayer=(i==(myISize-1));
       ShapeSupportID(bIsUpperLayer, aBNSSID, aSSID);
       if (myErrorStatus) {
         MESSAGE("StdMeshers_Penta_3D::MakeNodes() ");
@@ -418,6 +494,30 @@ void StdMeshers_Penta_3D::MakeNodes()
         if ( bIsUpperLayer ) {
           const SMDS_MeshNode* n = aTN.Node();
           myShapeXYZ[ SMESH_Block::ID_Fxy1 ].SetCoord( n->X(), n->Y(), n->Z() );
+          // set node on top face:
+          // find UV parameter for this node
+          //              UV_Ex11
+          //   UV011+-----+----------+UV111
+          //        |                |
+          //        |                |
+          // UV_E0y1+     +node      +UV_E1y1
+          //        |                |
+          //        |                |
+          //        |                |
+          //   UV001+-----+----------+UV101
+          //              UV_Ex01
+          gp_Pnt2d aP;
+          double u = aCoords.X(), v = aCoords.Y();
+          double u1 = ( 1. - u ), v1 = ( 1. - v );
+          aP.ChangeCoord()  = UV_Ex01 * v1;
+          aP.ChangeCoord() += UV_Ex11 * v;
+          aP.ChangeCoord() += UV_E0y1 * u1;
+          aP.ChangeCoord() += UV_E1y1 * u;
+          aP.ChangeCoord() -= UV001 * u1 * v1;
+          aP.ChangeCoord() -= UV101 * u  * v1;
+          aP.ChangeCoord() -= UV011 * u1 * v;
+          aP.ChangeCoord() -= UV111 * u  * v;
+          meshDS->SetNodeOnFace((SMDS_MeshNode*)n, topfaceID, aP.X(), aP.Y());
         }
       }
       if (myErrorStatus) {
@@ -456,10 +556,13 @@ void StdMeshers_Penta_3D::MakeNodes()
   */
   //DEB t
 }
+
+
 //=======================================================================
 //function : FindNodeOnShape
 //purpose  : 
 //=======================================================================
+
 void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
                                          const gp_XYZ&       aParams,
                                           const int           z,
@@ -470,14 +573,13 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
   double aX, aY, aZ, aD, aTol2, minD;
   gp_Pnt aP1, aP2;
   //
-  SMESH_Mesh* pMesh=GetMesh();
-  aTol2=myTol3D*myTol3D;
+  SMESH_Mesh* pMesh = GetMesh();
+  aTol2 = myTol3D*myTol3D;
   minD = 1.e100;
-  SMDS_MeshNode* pNode=NULL;
+  SMDS_MeshNode* pNode = NULL;
   //
   if ( aS.ShapeType() == TopAbs_FACE ||
-       aS.ShapeType() == TopAbs_EDGE )
-  {
+       aS.ShapeType() == TopAbs_EDGE ) {
     // find a face ID to which aTN belongs to
     int faceID;
     if ( aS.ShapeType() == TopAbs_FACE )
@@ -492,13 +594,13 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
     }
     ASSERT( SMESH_Block::IsFaceID( faceID ));
     int fIndex = SMESH_Block::ShapeIndex( faceID );
-    StdMeshers_IJNodeMap & ijNodes= myWallNodesMaps[ fIndex ];
+    StdMeshers_IJNodeMap & ijNodes = myWallNodesMaps[ fIndex ];
     // look for a base node in ijNodes
     const SMDS_MeshNode* baseNode = pMesh->GetMeshDS()->FindNode( aTN.BaseNodeID() );
     StdMeshers_IJNodeMap::const_iterator par_nVec = ijNodes.begin();
     for ( ; par_nVec != ijNodes.end(); par_nVec++ )
       if ( par_nVec->second[ 0 ] == baseNode ) {
-        pNode=(SMDS_MeshNode*)par_nVec->second.at( z );
+        pNode = (SMDS_MeshNode*)par_nVec->second.at( z );
         aTN.SetNode(pNode);
         return;
       }
@@ -510,6 +612,8 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
     pMesh->GetSubMeshContaining(aS)->GetSubMeshDS()->GetNodes();
   while(ite->more()) {
     const SMDS_MeshNode* aNode = ite->next();
+    if(myTool->IsMedium(aNode))
+      continue;
     aX=aNode->X();
     aY=aNode->Y();
     aZ=aNode->Z();
@@ -532,6 +636,7 @@ void StdMeshers_Penta_3D::FindNodeOnShape(const TopoDS_Shape& aS,
   //myErrorStatus=11; // can not find the node;
 }
 
+
 //=======================================================================
 //function : SetHorizEdgeXYZ
 //purpose  : 
@@ -583,6 +688,7 @@ double StdMeshers_Penta_3D::SetHorizEdgeXYZ(const gp_XYZ&                  aBase
   return r;
 }
 
+
 //=======================================================================
 //function : MakeVolumeMesh
 //purpose  : 
@@ -593,20 +699,20 @@ void StdMeshers_Penta_3D::MakeVolumeMesh()
   //
   int i, j, ij, ik, i1, i2, aSSID; 
   //
-  SMESH_Mesh*   pMesh =GetMesh();
-  SMESHDS_Mesh* meshDS=pMesh->GetMeshDS();
+  SMESH_Mesh*   pMesh = GetMesh();
+  SMESHDS_Mesh* meshDS = pMesh->GetMeshDS();
   //
   int shapeID = meshDS->ShapeToIndex( myShape );
   //
   // 1. Set Node In Volume
-  ik=myISize-1;
+  ik = myISize-1;
   for (i=1; i<ik; ++i){
     for (j=0; j<myJSize; ++j){
       ij=i*myJSize+j;
-      const StdMeshers_TNode& aTN=myTNodes[ij];
+      const StdMeshers_TNode& aTN = myTNodes[ij];
       aSSID=aTN.ShapeSupportID();
       if (aSSID==SMESH_Block::ID_NONE) {
-       SMDS_MeshNode* aNode=(SMDS_MeshNode*)aTN.Node();
+       SMDS_MeshNode* aNode = (SMDS_MeshNode*)aTN.Node();
        meshDS->SetNodeInVolume(aNode, shapeID);
       }
     }
@@ -621,22 +727,28 @@ void StdMeshers_Penta_3D::MakeVolumeMesh()
   const TopoDS_Face& aFxy0=
     TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy0));
   SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0);
-  SMESHDS_SubMesh *aSM0=aSubMesh0->GetSubMeshDS();
+  SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS();
   //
-  itf=aSM0->GetElements();
+  itf = aSM0->GetElements();
   while(itf->more()) {
-    const SMDS_MeshElement* pE0=itf->next();
+    const SMDS_MeshElement* pE0 = itf->next();
     //
     int nbFaceNodes = pE0->NbNodes();
+    if(myCreateQuadratic)
+      nbFaceNodes = nbFaceNodes/2;
     if ( aN.size() < nbFaceNodes * 2 )
       aN.resize( nbFaceNodes * 2 );
     //
     k=0;
     aItNodes=pE0->nodesIterator();
     while (aItNodes->more()) {
-      const SMDS_MeshElement* pNode=aItNodes->next();
-      aID0=pNode->GetID();
-      aJ[k]=GetIndexOnLayer(aID0);
+      //const SMDS_MeshElement* pNode = aItNodes->next();
+      const SMDS_MeshNode* pNode =
+        static_cast<const SMDS_MeshNode*> (aItNodes->next());
+      if(myTool->IsMedium(pNode))
+        continue;
+      aID0 = pNode->GetID();
+      aJ[k] = GetIndexOnLayer(aID0);
       if (myErrorStatus) {
         MESSAGE("StdMeshers_Penta_3D::MakeVolumeMesh");
        return;
@@ -646,19 +758,19 @@ void StdMeshers_Penta_3D::MakeVolumeMesh()
     }
     //
     bool forward = true;
-    for (i=0; i<ik; ++i){
+    for (i=0; i<ik; ++i) {
       i1=i;
       i2=i+1;
       for(j=0; j<nbFaceNodes; ++j) {
-       ij=i1*myJSize+aJ[j];
-       const StdMeshers_TNode& aTN1=myTNodes[ij];
-       const SMDS_MeshNode* aN1=aTN1.Node();
+       ij = i1*myJSize+aJ[j];
+       const StdMeshers_TNode& aTN1 = myTNodes[ij];
+       const SMDS_MeshNode* aN1 = aTN1.Node();
        aN[j]=aN1;
        //
        ij=i2*myJSize+aJ[j];
-       const StdMeshers_TNode& aTN2=myTNodes[ij];
-       const SMDS_MeshNode* aN2=aTN2.Node();
-       aN[j+nbFaceNodes]=aN2;
+       const StdMeshers_TNode& aTN2 = myTNodes[ij];
+       const SMDS_MeshNode* aN2 = aTN2.Node();
+       aN[j+nbFaceNodes] = aN2;
       }
       // check if volume orientation will be ok
       if ( i == 0 ) {
@@ -685,20 +797,30 @@ void StdMeshers_Penta_3D::MakeVolumeMesh()
       SMDS_MeshVolume* aV = 0;
       switch ( nbFaceNodes ) {
       case 3:
-        if ( forward )
-          aV = meshDS->AddVolume(aN[0], aN[1], aN[2],
-                                 aN[3], aN[4], aN[5]);
-        else
-          aV = meshDS->AddVolume(aN[0], aN[2], aN[1],
-                                 aN[3], aN[5], aN[4]);
+        if ( forward ) {
+          //aV = meshDS->AddVolume(aN[0], aN[1], aN[2],
+          //                       aN[3], aN[4], aN[5]);
+          aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3], aN[4], aN[5]);
+        }
+        else {
+          //aV = meshDS->AddVolume(aN[0], aN[2], aN[1],
+          //                       aN[3], aN[5], aN[4]);
+          aV = myTool->AddVolume(aN[0], aN[2], aN[1], aN[3], aN[5], aN[4]);
+        }
         break;
       case 4:
-        if ( forward )
-          aV = meshDS->AddVolume(aN[0], aN[1], aN[2], aN[3],
+        if ( forward ) {
+          //aV = meshDS->AddVolume(aN[0], aN[1], aN[2], aN[3],
+          //                       aN[4], aN[5], aN[6], aN[7]);
+          aV = myTool->AddVolume(aN[0], aN[1], aN[2], aN[3],
                                  aN[4], aN[5], aN[6], aN[7]);
-        else
-          aV = meshDS->AddVolume(aN[0], aN[3], aN[2], aN[1],
+        }
+        else {
+          //aV = meshDS->AddVolume(aN[0], aN[3], aN[2], aN[1],
+          //                       aN[4], aN[7], aN[6], aN[5]);
+          aV = myTool->AddVolume(aN[0], aN[3], aN[2], aN[1],
                                  aN[4], aN[7], aN[6], aN[5]);
+        }
         break;
       default:
         continue;
@@ -727,74 +849,68 @@ void StdMeshers_Penta_3D::MakeMeshOnFxy1()
   const TopoDS_Face& aFxy1=
     TopoDS::Face(myBlock.Shape(SMESH_Block::ID_Fxy1));
   //
-  SMESH_Mesh* pMesh=GetMesh();
+  SMESH_Mesh* pMesh = GetMesh();
   SMESHDS_Mesh * meshDS = pMesh->GetMeshDS();
   //
   SMESH_subMesh *aSubMesh0 = pMesh->GetSubMeshContaining(aFxy0);
-  SMESHDS_SubMesh *aSM0=aSubMesh0->GetSubMeshDS();
+  SMESHDS_SubMesh *aSM0 = aSubMesh0->GetSubMeshDS();
   //
   // set nodes on aFxy1
-  aLevel=myISize-1;
-  itn=aSM0->GetNodes();
-  aNbNodes=aSM0->NbNodes();
+  aLevel = myISize-1;
+  itn = aSM0->GetNodes();
+  aNbNodes = aSM0->NbNodes();
   //printf("** aNbNodes=%d\n", aNbNodes);
-  while(itn->more()) {
-    const SMDS_MeshNode* aN0=itn->next();
-    aID0=aN0->GetID();
-    aJ=GetIndexOnLayer(aID0);
-    if (myErrorStatus) {
-      MESSAGE("StdMeshers_Penta_3D::MakeMeshOnFxy1() ");
-      return;
-    }
-    //
-    ij=aLevel*myJSize+aJ;
-    const StdMeshers_TNode& aTN1=myTNodes[ij];
-    SMDS_MeshNode* aN1=(SMDS_MeshNode*)aTN1.Node();
-    //
-    meshDS->SetNodeOnFace(aN1, aFxy1);
-  }
+
   //
   // set elements on aFxy1
   vector<const SMDS_MeshNode*> aNodes1;
   //
-  itf=aSM0->GetElements();
+  itf = aSM0->GetElements();
   while(itf->more()) {
-    const SMDS_MeshElement * pE0=itf->next();
-    aElementType=pE0->GetType();
+    const SMDS_MeshElement* pE0 = itf->next();
+    aElementType = pE0->GetType();
     if (!aElementType==SMDSAbs_Face) {
       continue;
     }
-    aNbNodes=pE0->NbNodes();
+    aNbNodes = pE0->NbNodes();
+    if(myCreateQuadratic)
+      aNbNodes = aNbNodes/2;
 //     if (aNbNodes!=3) {
 //       continue;
 //     }
     if ( aNodes1.size() < aNbNodes )
       aNodes1.resize( aNbNodes );
     //
-    k=aNbNodes-1; // reverse a face
-    aItNodes=pE0->nodesIterator();
+    k = aNbNodes-1; // reverse a face
+    aItNodes = pE0->nodesIterator();
     while (aItNodes->more()) {
-      const SMDS_MeshElement* pNode=aItNodes->next();
-      aID0=pNode->GetID();
-      aJ=GetIndexOnLayer(aID0);
+      //const SMDS_MeshElement* pNode = aItNodes->next();
+      const SMDS_MeshNode* pNode =
+        static_cast<const SMDS_MeshNode*> (aItNodes->next());
+      if(myTool->IsMedium(pNode))
+        continue;
+      aID0 = pNode->GetID();
+      aJ = GetIndexOnLayer(aID0);
       if (myErrorStatus) {
         MESSAGE("StdMeshers_Penta_3D::MakeMeshOnFxy1() ");
        return;
       }
       //
-      ij=aLevel*myJSize+aJ;
-      const StdMeshers_TNode& aTN1=myTNodes[ij];
-      const SMDS_MeshNode* aN1=aTN1.Node();
-      aNodes1[k]=aN1;
+      ij = aLevel*myJSize + aJ;
+      const StdMeshers_TNode& aTN1 = myTNodes[ij];
+      const SMDS_MeshNode* aN1 = aTN1.Node();
+      aNodes1[k] = aN1;
       --k;
     }
     SMDS_MeshFace * face = 0;
     switch ( aNbNodes ) {
     case 3:
-      face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]);
+      //face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]);
+      face = myTool->AddFace(aNodes1[0], aNodes1[1], aNodes1[2]);
       break;
     case 4:
-      face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]);
+      //face = meshDS->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]);
+      face = myTool->AddFace(aNodes1[0], aNodes1[1], aNodes1[2], aNodes1[3]);
       break;
     default:
       continue;
@@ -802,6 +918,7 @@ void StdMeshers_Penta_3D::MakeMeshOnFxy1()
     meshDS->SetMeshElementOnShape(face, aFxy1);
   }
 }
+
 //=======================================================================
 //function : ClearMeshOnFxy1
 //purpose  : 
@@ -838,6 +955,7 @@ int StdMeshers_Penta_3D::GetIndexOnLayer(const int aID)
   j=(*aMapIt).second;
   return j;
 }
+
 //=======================================================================
 //function : MakeConnectingMap
 //purpose  : 
@@ -852,6 +970,7 @@ void StdMeshers_Penta_3D::MakeConnectingMap()
     myConnectingMap[aBNID]=j;
   }
 }
+
 //=======================================================================
 //function : CreateNode
 //purpose  : 
@@ -879,8 +998,7 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer,
 //     // point inside solid
 //     myBlock.Point(aParams, aP);
 //   }
-  if (bIsUpperLayer)
-  {
+  if (bIsUpperLayer) {
     double u = aParams.X(), v = aParams.Y();
     double u1 = ( 1. - u ), v1 = ( 1. - v );
     aP.ChangeCoord()  = myShapeXYZ[ SMESH_Block::ID_Ex01 ] * v1;
@@ -893,8 +1011,7 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer,
     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V011 ] * u1 * v;
     aP.ChangeCoord() -= myShapeXYZ[ SMESH_Block::ID_V111 ] * u  * v;
   }
-  else
-  {
+  else {
     SMESH_Block::ShellPoint( aParams, myShapeXYZ, aP.ChangeCoord() );
   }
   //
@@ -906,12 +1023,14 @@ void StdMeshers_Penta_3D::CreateNode(const bool bIsUpperLayer,
   //
   aX=aP.X(); aY=aP.Y(); aZ=aP.Z(); 
   //
-  SMESH_Mesh* pMesh=GetMesh();
-  SMESHDS_Mesh* pMeshDS=pMesh->GetMeshDS();
+  SMESH_Mesh* pMesh = GetMesh();
+  SMESHDS_Mesh* pMeshDS = pMesh->GetMeshDS();
   //
   pNode = pMeshDS->AddNode(aX, aY, aZ);
+  
   aTN.SetNode(pNode);
 }
+
 //=======================================================================
 //function : ShapeSupportID
 //purpose  : 
@@ -980,21 +1099,21 @@ void StdMeshers_Penta_3D::MakeBlock()
   SMDSAbs_ElementType aElementType;
   SMESH_Mesh* pMesh=GetMesh();
   //
-  iCnt=0;
-  iNbF=aM.Extent();
+  iCnt = 0;
+  iNbF = aM.Extent();
   for (i=1; i<=iNbF; ++i) {
-    const TopoDS_Shape& aF=aM(i);
+    const TopoDS_Shape& aF = aM(i);
     SMESH_subMesh *aSubMesh = pMesh->GetSubMeshContaining(aF);
     ASSERT(aSubMesh);
-    SMESHDS_SubMesh *aSM=aSubMesh->GetSubMeshDS();
-    SMDS_ElemIteratorPtr itf=aSM->GetElements();
+    SMESHDS_SubMesh *aSM = aSubMesh->GetSubMeshDS();
+    SMDS_ElemIteratorPtr itf = aSM->GetElements();
     while(itf->more()) {
-      const SMDS_MeshElement * pElement=itf->next();
-      aElementType=pElement->GetType();
+      const SMDS_MeshElement * pElement = itf->next();
+      aElementType = pElement->GetType();
       if (aElementType==SMDSAbs_Face) {
-       iNbNodes=pElement->NbNodes();
-       if (iNbNodes==3) {
-         aFTr=aF;
+       iNbNodes = pElement->NbNodes();
+       if ( iNbNodes==3 || (myCreateQuadratic && iNbNodes==6) ) {
+         aFTr = aF;
          ++iCnt;
          if (iCnt>1) {
             MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
@@ -1013,7 +1132,7 @@ void StdMeshers_Penta_3D::MakeBlock()
   TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMVES);
   //
   // 1.1 Base vertex V000
-  iNbE=aME.Extent();
+  iNbE = aME.Extent();
   if (iNbE!=4){
     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
     myErrorStatus=7; // too few edges are in base face aFTr 
@@ -1080,7 +1199,7 @@ void StdMeshers_Penta_3D::MakeBlock()
   // 2. Load Block
   const TopoDS_Shell& aShell=TopoDS::Shell(aME(1));
   myBlock.Load(aShell, aV000, aV001);
-  iErr=myBlock.ErrorStatus();
+  iErr = myBlock.ErrorStatus();
   if (iErr) {
     MESSAGE("StdMeshers_Penta_3D::MakeBlock() ");
     myErrorStatus=100; // SMESHBlock: Load operation failed
@@ -1154,10 +1273,10 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
   bool rev1, CumOri = false;
   TopExp_Explorer exp( theFace, TopAbs_EDGE );
   int nbEdges = 0;
-  for ( ; exp.More(); exp.Next() )
-  {
-    if ( ++nbEdges > 4 )
+  for ( ; exp.More(); exp.Next() ) {
+    if ( ++nbEdges > 4 ) {
       return false; // more than 4 edges in theFace
+    }
     TopoDS_Edge e = TopoDS::Edge( exp.Current() );
     if ( theBaseEdge.IsSame( e ))
       continue;
@@ -1174,8 +1293,9 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
     else
       e2 = e;
   }
-  if ( nbEdges < 4 )
-    return false; // lass than 4 edges in theFace
+  if ( nbEdges < 4 ) {
+    return false; // less than 4 edges in theFace
+  }
 
   // submeshes corresponding to shapes
   SMESHDS_SubMesh* smFace = theMesh->MeshElements( theFace );
@@ -1200,13 +1320,32 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
     return false;
   }
   if ( sm1->NbNodes() * smb->NbNodes() != smFace->NbNodes() ) {
-    MESSAGE( "Wrong nb face nodes: " <<
-            sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
-    return false;
+    // check quadratic case
+    if ( myCreateQuadratic ) {
+      int n1 = sm1->NbNodes()/2;
+      int n2 = smb->NbNodes()/2;
+      int n3 = sm1->NbNodes() - n1;
+      int n4 = smb->NbNodes() - n2;
+      int nf = sm1->NbNodes()*smb->NbNodes() - n3*n4;
+      if( nf != smFace->NbNodes() ) {
+        MESSAGE( "Wrong nb face nodes: " <<
+                sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
+        return false;
+      }
+    }
+    else {
+      MESSAGE( "Wrong nb face nodes: " <<
+              sm1->NbNodes()<<" "<<smb->NbNodes()<<" "<<smFace->NbNodes());
+      return false;
+    }
   }
   // IJ size
   int vsize = sm1->NbNodes() + 2;
   int hsize = smb->NbNodes() + 2;
+  if(myCreateQuadratic) {
+    vsize = vsize - sm1->NbNodes()/2 -1;
+    hsize = hsize - smb->NbNodes()/2 -1;
+  }
 
   // load nodes from theBaseEdge
 
@@ -1226,12 +1365,15 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
   double range = l - f;
   SMDS_NodeIteratorPtr nIt = smb->GetNodes();
   const SMDS_MeshNode* node;
-  while ( nIt->more() )
-  {
+  while ( nIt->more() ) {
     node = nIt->next();
+    if(myTool->IsMedium(node))
+      continue;
     const SMDS_EdgePosition* pos =
       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
-    if ( !pos ) return false;
+    if ( !pos ) {
+      return false;
+    }
     double u = ( pos->GetUParameter() - f ) / range;
     vector<const SMDS_MeshNode*> & nVec = theIJNodes[ u ];
     nVec.resize( vsize, nullNode );
@@ -1246,19 +1388,21 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
 
   map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge
   nIt = sm1->GetNodes();
-  while ( nIt->more() )
-  {
+  while ( nIt->more() ) {
     node = nIt->next();
+    if(myTool->IsMedium(node))
+      continue;
     const SMDS_EdgePosition* pos =
       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
-    if ( !pos ) return false;
+    if ( !pos ) {
+      return false;
+    }
     sortedNodes.insert( make_pair( pos->GetUParameter(), node ));
   }
   loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() );
   map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin();
   int row = rev1 ? vsize - 1 : 0;
-  for ( ; u_n != sortedNodes.end(); u_n++ )
-  {
+  for ( ; u_n != sortedNodes.end(); u_n++ ) {
     if ( rev1 ) row--;
     else        row++;
     loadedNodes.insert( nVecf[ row ] = u_n->second );
@@ -1285,8 +1429,7 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
   StdMeshers_IJNodeMap::iterator par_nVec_2 = par_nVec_1;
   // loop on columns
   int col = 0;
-  for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ )
-  {
+  for ( par_nVec_2++; par_nVec_2 != theIJNodes.end(); par_nVec_1++, par_nVec_2++ ) {
     col++;
     row = 0;
     const SMDS_MeshNode* n1 = par_nVec_1->second[ row ];
@@ -1295,10 +1438,10 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
     do {
       // look for a face by 2 nodes
       face = SMESH_MeshEditor::FindFaceInSet( n1, n2, allFaces, foundFaces );
-      if ( face )
-      {
+      if ( face ) {
         int nbFaceNodes = face->NbNodes();
-        if ( nbFaceNodes > 4 ) {
+        if ( (!myCreateQuadratic && nbFaceNodes>4) ||
+             (myCreateQuadratic && nbFaceNodes>8) ) {
           MESSAGE(" Too many nodes in a face: " << nbFaceNodes );
           return false;
         }
@@ -1308,6 +1451,8 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
         eIt = face->nodesIterator() ;
         while ( !found && eIt->more() ) {
           node = static_cast<const SMDS_MeshNode*>( eIt->next() );
+          if(myTool->IsMedium(node))
+            continue;
           found = loadedNodes.insert( node ).second;
           if ( !found && node != n1 && node != n2 )
             n3 = node;
@@ -1320,18 +1465,21 @@ bool StdMeshers_Penta_3D::LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
           par_nVec_2->second[ row ] = node;
           foundFaces.insert( face );
           n2 = node;
-          if ( nbFaceNodes == 4 )
+          if ( nbFaceNodes==4 || (myCreateQuadratic && nbFaceNodes==8) ) {
             n1 = par_nVec_1->second[ row ];
+          }
         }
-        else if (nbFaceNodes == 3 &&
-                 n3 == par_nVec_1->second[ row ] )
+        else if ( (nbFaceNodes==3 || (myCreateQuadratic && nbFaceNodes==6) )  &&
+                 n3 == par_nVec_1->second[ row ] ) {
           n1 = n3;
+        }
         else {
           MESSAGE( "Not quad mesh, column "<< col );
           return false;
         }
       }
-    } while ( face && n1 && n2 );
+    }
+    while ( face && n1 && n2 );
 
     if ( row < vsize - 1 ) {
       MESSAGE( "Too few nodes in column "<< col <<": "<< row+1);
@@ -1390,17 +1538,18 @@ int StdMeshers_SMESHBlock::ErrorStatus() const
 {
   return myErrorStatus;
 }
+
 //=======================================================================
 //function : Load
 //purpose  : 
 //=======================================================================
 void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell)
 {
-  
   TopoDS_Vertex aV000, aV001;
   //
   Load(theShell, aV000, aV001);
 }
+
 //=======================================================================
 //function : Load
 //purpose  : 
@@ -1416,12 +1565,13 @@ void StdMeshers_SMESHBlock::Load(const TopoDS_Shell& theShell,
   bool bOk;
   //
   myShapeIDMap.Clear();  
-  bOk=myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap);
+  bOk = myTBlock.LoadBlockShapes(myShell, theV000, theV001, myShapeIDMap);
   if (!bOk) {
     myErrorStatus=2;
     return;
   }
 }
+
 //=======================================================================
 //function : ComputeParameters
 //purpose  : 
@@ -1431,24 +1581,25 @@ void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt,
 {
   ComputeParameters(thePnt, myShell, theXYZ);
 }
+
 //=======================================================================
 //function : ComputeParameters
 //purpose  : 
 //=======================================================================
 void StdMeshers_SMESHBlock::ComputeParameters(const gp_Pnt& thePnt,
                                              const TopoDS_Shape& theShape,
-                                             gp_XYZ& theXYZ)
+                                              gp_XYZ& theXYZ)
 {
   myErrorStatus=0;
   //
   int aID;
   bool bOk;
   //
-  aID=ShapeID(theShape);
+  aID = ShapeID(theShape);
   if (myErrorStatus) {
     return;
   }
-  bOk=myTBlock.ComputeParameters(thePnt, theXYZ, aID);
+  bOk = myTBlock.ComputeParameters(thePnt, theXYZ, aID);
   if (!bOk) {
     myErrorStatus=4; // problems with computation Parameters 
     return;
@@ -1469,12 +1620,12 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
   int aID;
   bool bOk=false;
   //
-  aID=ShapeID(theShape);
+  aID = ShapeID(theShape);
   if (myErrorStatus) {
     return;
   }
   if ( SMESH_Block::IsEdgeID( aID ))
-      bOk=myTBlock.EdgeParameters( aID, theU, theXYZ );
+      bOk = myTBlock.EdgeParameters( aID, theU, theXYZ );
   if (!bOk) {
     myErrorStatus=4; // problems with computation Parameters 
     return;
@@ -1492,6 +1643,7 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
   //
   Point(theParams, aS, aP3D);
 }
+
 //=======================================================================
 //function : Point
 //purpose  : 
@@ -1500,15 +1652,15 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
                                   const TopoDS_Shape& theShape,
                                   gp_Pnt& aP3D)
 {
-  myErrorStatus=0;
+  myErrorStatus = 0;
   //
   int aID;
-  bool bOk=false;
+  bool bOk = false;
   gp_XYZ aXYZ(99.,99.,99.);
   aP3D.SetXYZ(aXYZ);
   //
   if (theShape.IsNull()) {
-    bOk=myTBlock.ShellPoint(theParams, aXYZ);
+    bOk = myTBlock.ShellPoint(theParams, aXYZ);
   }
   //
   else {
@@ -1518,14 +1670,14 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
     }
     //
     if (SMESH_Block::IsVertexID(aID)) {
-      bOk=myTBlock.VertexPoint(aID, aXYZ);
+      bOk = myTBlock.VertexPoint(aID, aXYZ);
     }
     else if (SMESH_Block::IsEdgeID(aID)) {
-      bOk=myTBlock.EdgePoint(aID, theParams, aXYZ);
+      bOk = myTBlock.EdgePoint(aID, theParams, aXYZ);
     }
     //
     else if (SMESH_Block::IsFaceID(aID)) {
-      bOk=myTBlock.FacePoint(aID, theParams, aXYZ);
+      bOk = myTBlock.FacePoint(aID, theParams, aXYZ);
     }
   }
   if (!bOk) {
@@ -1534,6 +1686,7 @@ void StdMeshers_SMESHBlock::ComputeParameters(const double& theU,
   }
   aP3D.SetXYZ(aXYZ);
 }
+
 //=======================================================================
 //function : ShapeID
 //purpose  : 
@@ -1561,6 +1714,7 @@ int StdMeshers_SMESHBlock::ShapeID(const TopoDS_Shape& theShape)
   myErrorStatus=2; // unknown shape;
   return aID;
 }
+
 //=======================================================================
 //function : Shape
 //purpose  : 
@@ -1580,3 +1734,5 @@ const TopoDS_Shape& StdMeshers_SMESHBlock::Shape(const int theID)
   const TopoDS_Shape& aS=myShapeIDMap.FindKey(theID);
   return aS;
 }
+
+
index dc8ba72cfe44ab531880ee08ea96c5a7a5d5441b..1b5efab6d79d7f9ce54d54ae746982537f46c47b 100644 (file)
 #include <TopoDS_Vertex.hxx>
 #include <TopoDS_Shell.hxx>
 #include <TopTools_IndexedMapOfOrientedShape.hxx>
+#include <TColStd_MapOfInteger.hxx>
 
 #include "SMESH_Block.hxx"
 
+#include "StdMeshers_Helper.hxx"
+
 typedef std::map< double, std::vector<const SMDS_MeshNode*> > StdMeshers_IJNodeMap;
 
 class StdMeshers_SMESHBlock {
@@ -181,10 +184,10 @@ class StdMeshers_Penta_3D {
       return myTol3D;
     }
 
-    static bool LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
-                            const TopoDS_Face&     theFace,
-                            const TopoDS_Edge&     theBaseEdge,
-                            SMESHDS_Mesh*          theMesh);
+    bool LoadIJNodes(StdMeshers_IJNodeMap & theIJNodes,
+                     const TopoDS_Face&     theFace,
+                     const TopoDS_Edge&     theBaseEdge,
+                     SMESHDS_Mesh*          theMesh);
     // Load nodes bound to theFace into column (vectors) and rows
     // of theIJNodes.
     // The value of theIJNodes map is a vector of ordered nodes so
@@ -251,6 +254,9 @@ class StdMeshers_Penta_3D {
     //
     vector<StdMeshers_IJNodeMap> myWallNodesMaps; // nodes on a face
     vector<gp_XYZ>            myShapeXYZ; // point on each sub-shape
+
+    bool myCreateQuadratic;
+    StdMeshers_Helper* myTool; // toll for working with quadratic elements
 };
 
 #endif
index 9ffa37d1f5ebf675ef727015f57a62f0550f4a3f..3a2eb87803d1a7ba25d52e8a8c115616817a0b06 100644 (file)
@@ -47,6 +47,7 @@ using namespace std;
 #include <Geom2d_Curve.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <GCPnts_UniformAbscissa.hxx>
+#include <TopExp.hxx>
 
 #include <Precision.hxx>
 #include <gp_Pnt2d.hxx>
@@ -128,6 +129,11 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
   aMesh.GetSubMesh(aShape);
 
+  bool QuadMode = true;
+
+  myTool = new StdMeshers_Helper(aMesh);
+  myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode);
+
   //FaceQuadStruct *quad = CheckAnd2Dcompute(aMesh, aShape);
   FaceQuadStruct* quad = CheckNbEdges(aMesh, aShape);
 
@@ -180,7 +186,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       quad->uv_grid[ij].node = node;
     }
   }
-
+  
   // mesh faces
 
   //             [2]
@@ -194,16 +200,16 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   //     0 > > > > > > > > nbhoriz
   //              i
   //             [0]
-
+  
   i = 0;
   int ilow = 0;
   int iup = nbhoriz - 1;
   if (quad->isEdgeOut[3]) { ilow++; } else { if (quad->isEdgeOut[1]) iup--; }
-
+  
   int jlow = 0;
   int jup = nbvertic - 1;
   if (quad->isEdgeOut[0]) { jlow++; } else { if (quad->isEdgeOut[2]) jup--; }
-
+  
   // regular quadrangles
   for (i = ilow; i < iup; i++) {
     for (j = jlow; j < jup; j++) {
@@ -212,11 +218,12 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       b = quad->uv_grid[j * nbhoriz + i + 1].node;
       c = quad->uv_grid[(j + 1) * nbhoriz + i + 1].node;
       d = quad->uv_grid[(j + 1) * nbhoriz + i].node;
-      SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d);
+      //SMDS_MeshFace * face = meshDS->AddFace(a, b, c, d);
+      SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
       meshDS->SetMeshElementOnShape(face, geomFaceID);
     }
   }
-
+  
   UVPtStruct *uv_e0 = quad->uv_edges[0];
   UVPtStruct *uv_e1 = quad->uv_edges[1];
   UVPtStruct *uv_e2 = quad->uv_edges[2];
@@ -225,7 +232,7 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
   double eps = Precision::Confusion();
 
   // Boundary quadrangles
-
+  
   if (quad->isEdgeOut[0]) {
     // Down edge is out
     // 
@@ -237,14 +244,14 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
     // .  .  .  .  .  .  .  .  . __ down edge nodes
     // 
     // >->->->->->->->->->->->-> -- direction of processing
-
+      
     int g = 0; // number of last processed node in the regular grid
-
+    
     // number of last node of the down edge to be processed
     int stop = nbdown - 1;
     // if right edge is out, we will stop at a node, previous to the last one
     if (quad->isEdgeOut[1]) stop--;
-
+    
     // for each node of the down edge find nearest node
     // in the first row of the regular grid and link them
     for (i = 0; i < stop; i++) {
@@ -252,18 +259,19 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       a = uv_e0[i].node;
       b = uv_e0[i + 1].node;
       gp_Pnt pb (b->X(), b->Y(), b->Z());
-
+      
       // find node c in the regular grid, which will be linked with node b
       int near = g;
       if (i == stop - 1) {
         // right bound reached, link with the rightmost node
         near = iup;
         c = quad->uv_grid[nbhoriz + iup].node;
-      } else {
+      }
+      else {
         // find in the grid node c, nearest to the b
         double mind = RealLast();
         for (int k = g; k <= iup; k++) {
-
+          
           const SMDS_MeshNode *nk;
           if (k < ilow) // this can be, if left edge is out
             nk = uv_e3[1].node; // get node from the left edge
@@ -283,14 +291,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       }
 
       if (near == g) { // make triangle
-        SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+        //SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+        SMDS_MeshFace* face = myTool->AddFace(a, b, c);
         meshDS->SetMeshElementOnShape(face, geomFaceID);
-      } else { // make quadrangle
+      }
+      else { // make quadrangle
         if (near - 1 < ilow)
           d = uv_e3[1].node;
         else
           d = quad->uv_grid[nbhoriz + near - 1].node;
-        SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+        //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+        SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
         meshDS->SetMeshElementOnShape(face, geomFaceID);
 
         // if node d is not at position g - make additional triangles
@@ -301,7 +312,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
               d = uv_e3[1].node;
             else
               d = quad->uv_grid[nbhoriz + k - 1].node;
-            SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+            //SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+            SMDS_MeshFace* face = myTool->AddFace(a, c, d);
             meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
         }
@@ -363,14 +375,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
         }
 
         if (near == g) { // make triangle
-          SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+          //SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+          SMDS_MeshFace* face = myTool->AddFace(a, b, c);
           meshDS->SetMeshElementOnShape(face, geomFaceID);
-        } else { // make quadrangle
+        }
+        else { // make quadrangle
           if (near + 1 > iup)
             d = uv_e1[nbright - 2].node;
           else
             d = quad->uv_grid[nbhoriz*(nbvertic - 2) + near + 1].node;
-          SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+          //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+          SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
           meshDS->SetMeshElementOnShape(face, geomFaceID);
 
           if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -380,7 +395,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
                 d = uv_e1[nbright - 2].node;
               else
                 d = quad->uv_grid[nbhoriz*(nbvertic - 2) + k + 1].node;
-              SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+              //SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+              SMDS_MeshFace* face = myTool->AddFace(a, c, d);
               meshDS->SetMeshElementOnShape(face, geomFaceID);
             }
           }
@@ -428,14 +444,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
       }
 
       if (near == g) { // make triangle
-        SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+        //SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+        SMDS_MeshFace* face = myTool->AddFace(a, b, c);
         meshDS->SetMeshElementOnShape(face, geomFaceID);
-      } else { // make quadrangle
+      }
+      else { // make quadrangle
         if (near - 1 < jlow)
           d = uv_e0[nbdown - 2].node;
         else
           d = quad->uv_grid[nbhoriz*near - 2].node;
-        SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+        //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+        SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
         meshDS->SetMeshElementOnShape(face, geomFaceID);
 
         if (near - 1 > g) { // if d not is at g - make additional triangles
@@ -445,7 +464,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
               d = uv_e0[nbdown - 2].node;
             else
               d = quad->uv_grid[nbhoriz*k - 2].node;
-            SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+            //SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+            SMDS_MeshFace* face = myTool->AddFace(a, c, d);
             meshDS->SetMeshElementOnShape(face, geomFaceID);
           }
         }
@@ -490,14 +510,17 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
         }
 
         if (near == g) { // make triangle
-          SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+          //SMDS_MeshFace* face = meshDS->AddFace(a, b, c);
+          SMDS_MeshFace* face = myTool->AddFace(a, b, c);
           meshDS->SetMeshElementOnShape(face, geomFaceID);
-        } else { // make quadrangle
+        }
+        else { // make quadrangle
           if (near + 1 > jup)
             d = uv_e2[1].node;
           else
             d = quad->uv_grid[nbhoriz*(near + 1) + 1].node;
-          SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+          //SMDS_MeshFace* face = meshDS->AddFace(a, b, c, d);
+          SMDS_MeshFace* face = myTool->AddFace(a, b, c, d);
           meshDS->SetMeshElementOnShape(face, geomFaceID);
 
           if (near + 1 < g) { // if d not is at g - make additional triangles
@@ -507,7 +530,8 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh,
                 d = uv_e2[1].node;
               else
                 d = quad->uv_grid[nbhoriz*(k + 1) + 1].node;
-              SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+              //SMDS_MeshFace* face = meshDS->AddFace(a, c, d);
+              SMDS_MeshFace* face = myTool->AddFace(a, c, d);
               meshDS->SetMeshElementOnShape(face, geomFaceID);
             }
           }
@@ -557,7 +581,13 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMesh,
     int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
     if (nbEdges < 4) {
       quad->edge[nbEdges] = E;
-      quad->nbPts[nbEdges] = nb + 2; // internal points + 2 extrema
+      if(!myCreateQuadratic) {
+        quad->nbPts[nbEdges] = nb + 2; // internal points + 2 extrema
+      }
+      else {
+        int tmp = nb/2;
+        quad->nbPts[nbEdges] = tmp + 2; // internal not medium points + 2 extrema
+      }
     }
     nbEdges++;
   }
@@ -574,15 +604,35 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMesh,
 
 //=============================================================================
 /*!
- *  
+ *  CheckAnd2Dcompute
  */
 //=============================================================================
 
 FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute
   (SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) throw(SALOME_Exception)
+{
+  bool QuadMode = true;
+  myTool = new StdMeshers_Helper(aMesh);
+  myCreateQuadratic = myTool->IsQuadraticSubMesh(aShape,QuadMode);
+  return CheckAnd2Dcompute(aMesh,aShape,myCreateQuadratic);
+}
+
+
+//=============================================================================
+/*!
+ *  CheckAnd2Dcompute
+ */
+//=============================================================================
+
+FaceQuadStruct *StdMeshers_Quadrangle_2D::CheckAnd2Dcompute
+                           (SMESH_Mesh & aMesh,
+                            const TopoDS_Shape & aShape,
+                            const bool CreateQuadratic) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
 
+  myCreateQuadratic = CreateQuadratic;
+
   FaceQuadStruct *quad = CheckNbEdges(aMesh, aShape);
 
   if(!quad) return 0;
@@ -1185,13 +1235,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref
       for(j=1; j<nl; j++) {
         if(WisF) {
           SMDS_MeshFace* F =
-            meshDS->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
+            myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i+1,j),
                             NodesL.Value(i+1,j+1), NodesL.Value(i,j+1));
           meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
-            meshDS->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1),
+            myTool->AddFace(NodesL.Value(i,j), NodesL.Value(i,j+1),
                             NodesL.Value(i+1,j+1), NodesL.Value(i+1,j));
           meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
@@ -1252,13 +1302,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref
       for(j=1; j<nr; j++) {
         if(WisF) {
           SMDS_MeshFace* F =
-            meshDS->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
+            myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i+1,j),
                             NodesR.Value(i+1,j+1), NodesR.Value(i,j+1));
           meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
         else {
           SMDS_MeshFace* F =
-            meshDS->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1),
+            myTool->AddFace(NodesR.Value(i,j), NodesR.Value(i,j+1),
                             NodesR.Value(i+1,j+1), NodesR.Value(i+1,j));
           meshDS->SetMeshElementOnShape(F, geomFaceID);
         }
@@ -1335,13 +1385,13 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref
     for(j=1; j<nbv; j++) {
       if(WisF) {
         SMDS_MeshFace* F =
-          meshDS->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
+          myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i+1,j),
                           NodesC.Value(i+1,j+1), NodesC.Value(i,j+1));
         meshDS->SetMeshElementOnShape(F, geomFaceID);
       }
       else {
         SMDS_MeshFace* F =
-          meshDS->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
+          myTool->AddFace(NodesC.Value(i,j), NodesC.Value(i,j+1),
                           NodesC.Value(i+1,j+1), NodesC.Value(i+1,j));
         meshDS->SetMeshElementOnShape(F, geomFaceID);
       }
@@ -1387,18 +1437,64 @@ UVPtStruct* StdMeshers_Quadrangle_2D::LoadEdgePoints2 (SMESH_Mesh & aMesh,
 
   // --- edge internal IDNodes (relies on good order storage, not checked)
 
+//  if(myCreateQuadratic) {
+    // fill myNLinkNodeMap
+//    SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements();
+//    while(iter->more()) {
+//      const SMDS_MeshElement* elem = iter->next();
+//      SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+//      const SMDS_MeshNode* n1 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      const SMDS_MeshNode* n2 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      const SMDS_MeshNode* n3 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+//      myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3));
+//      myNLinkNodeMap[link] = n3;
+//    }
+//  }
+
   map<double, const SMDS_MeshNode *> params;
   SMDS_NodeIteratorPtr ite = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
+  int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
 
-  while(ite->more()) {
-    const SMDS_MeshNode* node = ite->next();
-    const SMDS_EdgePosition* epos =
-      static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
-    double param = epos->GetUParameter();
-    params[param] = node;
+  if(!myCreateQuadratic) {
+    while(ite->more()) {
+      const SMDS_MeshNode* node = ite->next();
+      const SMDS_EdgePosition* epos =
+        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+      double param = epos->GetUParameter();
+      params[param] = node;
+    }
+  }
+  else {
+    vector<const SMDS_MeshNode*> nodes(nbPoints+2);
+    nodes[0] = idFirst;
+    nodes[nbPoints+1] = idLast;
+    nbPoints = nbPoints/2;
+    int nn = 1;
+    while(ite->more()) {
+      const SMDS_MeshNode* node = ite->next();
+      nodes[nn++] = node;
+      // check if node is medium
+      bool IsMedium = false;
+      SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator();
+      while (itn->more()) {
+        const SMDS_MeshElement* elem = itn->next();
+        if ( elem->GetType() != SMDSAbs_Edge )
+          continue;
+        if(elem->IsMediumNode(node)) {
+          IsMedium = true;
+          break;
+        }
+      }
+      if(IsMedium)
+        continue;
+      const SMDS_EdgePosition* epos =
+        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+      double param = epos->GetUParameter();
+      params[param] = node;
+    }
   }
 
-  int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
   if (nbPoints != params.size()) {
     MESSAGE( "BAD NODE ON EDGE POSITIONS" );
     return 0;
@@ -1523,21 +1619,60 @@ UVPtStruct* StdMeshers_Quadrangle_2D::LoadEdgePoints (SMESH_Mesh & aMesh,
 
   // --- edge internal IDNodes (relies on good order storage, not checked)
 
+//  if(myCreateQuadratic) {
+    // fill myNLinkNodeMap
+//    SMDS_ElemIteratorPtr iter = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetElements();
+//    while(iter->more()) {
+//      const SMDS_MeshElement* elem = iter->next();
+//      SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+//      const SMDS_MeshNode* n1 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      const SMDS_MeshNode* n2 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      const SMDS_MeshNode* n3 = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+//      NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
+//      myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n3));
+//      myNLinkNodeMap[link] = n3;
+//    }
+//  }
+
   map<double, const SMDS_MeshNode *> params;
   SMDS_NodeIteratorPtr ite = aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
+  int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
 
-  while(ite->more())
-  {
-    const SMDS_MeshNode* node = ite->next();
-    const SMDS_EdgePosition* epos =
-      static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
-    double param = epos->GetUParameter();
-    params[param] = node;
+  if(!myCreateQuadratic) {
+    while(ite->more()) {
+      const SMDS_MeshNode* node = ite->next();
+      const SMDS_EdgePosition* epos =
+        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+      double param = epos->GetUParameter();
+      params[param] = node;
+    }
+  }
+  else {
+    nbPoints = nbPoints/2;
+    while(ite->more()) {
+      const SMDS_MeshNode* node = ite->next();
+      // check if node is medium
+      bool IsMedium = false;
+      SMDS_ElemIteratorPtr itn = node->GetInverseElementIterator();
+      while (itn->more()) {
+        const SMDS_MeshElement* elem = itn->next();
+        if ( elem->GetType() != SMDSAbs_Edge )
+          continue;
+        if(elem->IsMediumNode(node)) {
+          IsMedium = true;
+          break;
+        }
+      }
+      if(IsMedium)
+        continue;
+      const SMDS_EdgePosition* epos =
+        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+      double param = epos->GetUParameter();
+      params[param] = node;
+    }
   }
 
-  int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
-  if (nbPoints != params.size())
-  {
+  if (nbPoints != params.size()) {
     MESSAGE( "BAD NODE ON EDGE POSITIONS" );
     return 0;
   }
index afb3498cbdba6a3923dd00229c21e61ff3aa4947..437910c198cc1c0e19d4f9f7c27914c5d0c3f66b 100644 (file)
 #include "SMESH_Mesh.hxx"
 #include "Utils_SALOME_Exception.hxx"
 
-class SMDS_MeshNode;
+#include "gp_XY.hxx"
+
+#include "StdMeshers_Helper.hxx"
+
+//class SMDS_MeshNode;
 
 typedef struct uvPtStruct
 {
@@ -78,8 +82,18 @@ public:
                                    const TopoDS_Shape& aShape)
     throw (SALOME_Exception);
 
+  FaceQuadStruct* CheckAnd2Dcompute(SMESH_Mesh& aMesh,
+                                   const TopoDS_Shape& aShape,
+                                    const bool CreateQuadratic)
+    throw (SALOME_Exception);
+
   static void QuadDelete(FaceQuadStruct* quad);
 
+  /**
+   * Returns NLinkNodeMap from myTool
+   */
+  const NLinkNodeMap& GetNLinkNodeMap() { return myTool->GetNLinkNodeMap(); }
+
   ostream & SaveTo(ostream & save);
   istream & LoadFrom(istream & load);
   friend ostream & operator << (ostream & save, StdMeshers_Quadrangle_2D & hyp);
@@ -120,6 +134,8 @@ protected:
   // construction of quadrangles if the number of nodes on opposite edges
   // is not the same in the case where the global number of nodes on edges is even
   bool myQuadranglePreference;
+
+  StdMeshers_Helper* myTool; // toll for working with quadratic elements
 };
 
 #endif
index 86b4379c37282c7585f25a64e5efaca7a19ec018..ebb8ed9ec315da3f27d8148761caec1284373b02 100644 (file)
@@ -42,7 +42,10 @@ StdMeshers_QuadraticMesh::StdMeshers_QuadraticMesh(int         hypId,
      :SMESH_Hypothesis(hypId, studyId, gen)
 {
   _name = "QuadraticMesh";
-  _param_algo_dim = 1; // is used by StdMeshers_Regular_1D
+  // only one hypo of the same dim can be assigned to the shape so
+  // we use -3 in order to distingush from any usual 1D hypothsis and
+  // from "NotConformAllowed" (-1) and "Propagation" (-2)
+  _param_algo_dim = -3;
 }
 
 //=============================================================================
index d3d92f9ea20d8a66a327c83c04ee3208f5623fbc..c3eb48483eda0aa5ee6656e3a020645e225dbf87 100644 (file)
@@ -510,7 +510,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
 
   // quardatic mesh required?
   SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "QuadraticMesh" ));
-  bool isQuadraticMesh = aMesh->GetHypothesis( aShape, filter, true );
+  bool QuadMode = aMesh.GetHypothesis( aShape, filter, true );
 
   const TopoDS_Edge & EE = TopoDS::Edge(aShape);
   TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
@@ -533,15 +533,13 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
 
   ASSERT(!VLast.IsNull());
   lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
-  if (!lid->more())
-  {
+  if (!lid->more()) {
     MESSAGE (" NO NODE BUILT ON VERTEX ");
     return false;
   }
   const SMDS_MeshNode * idLast = lid->next();
 
-  if (!Curve.IsNull())
-  {
+  if (!Curve.IsNull()) {
     list< double > params;
     bool reversed = false;
     if ( !_mainEdge.IsNull() )
@@ -558,9 +556,14 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
     // only internal nodes receive an edge position with param on curve
 
     const SMDS_MeshNode * idPrev = idFirst;
+    double parPrev = f;
+    double parLast = l;
+    if(reversed) {
+      parPrev = l;
+      parLast = f;
+    }
     
-    for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
-    {
+    for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
       double param = *itU;
       gp_Pnt P = Curve->Value(param);
 
@@ -568,15 +571,37 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
       SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
       meshDS->SetNodeOnEdge(node, shapeID, param);
 
-      SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
-      meshDS->SetMeshElementOnShape(edge, shapeID);
+      if(QuadMode) {
+        // create medium node
+        double prm = ( parPrev + param )/2;
+        gp_Pnt PM = Curve->Value(prm);
+        SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
+        meshDS->SetNodeOnEdge(NM, shapeID, prm);
+        SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
+        meshDS->SetMeshElementOnShape(edge, shapeID);
+      }
+      else {
+        SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
+        meshDS->SetMeshElementOnShape(edge, shapeID);
+      }
+
       idPrev = node;
+      parPrev = param;
+    }
+    if(QuadMode) {
+      double prm = ( parPrev + parLast )/2;
+      gp_Pnt PM = Curve->Value(prm);
+      SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
+      meshDS->SetNodeOnEdge(NM, shapeID, prm);
+      SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
+      meshDS->SetMeshElementOnShape(edge, shapeID);
+    }
+    else {
+      SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
+      meshDS->SetMeshElementOnShape(edge, shapeID);
     }
-    SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
-    meshDS->SetMeshElementOnShape(edge, shapeID);
   }
-  else
-  {
+  else {
     // Edge is a degenerated Edge : We put n = 5 points on the edge.
     int NbPoints = 5;
     BRep_Tool::Range(E, f, l);
@@ -588,18 +613,38 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
     gp_Pnt P = BRep_Tool::Pnt(V1);
 
     const SMDS_MeshNode * idPrev = idFirst;
-    for (int i = 2; i < NbPoints; i++)
-    {
+    for (int i = 2; i < NbPoints; i++) {
       double param = f + (i - 1) * du;
       SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+      if(QuadMode) {
+        // create medium node
+        double prm = param - du/2.;
+        gp_Pnt PM = Curve->Value(prm);
+        SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
+        meshDS->SetNodeOnEdge(NM, shapeID, prm);
+        SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
+        meshDS->SetMeshElementOnShape(edge, shapeID);
+      }
+      else {
+        SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
+        meshDS->SetMeshElementOnShape(edge, shapeID);
+      }
       meshDS->SetNodeOnEdge(node, shapeID, param);
-
-      SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
-      meshDS->SetMeshElementOnShape(edge, shapeID);
       idPrev = node;
     }
-    SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
-    meshDS->SetMeshElementOnShape(edge, shapeID);
+    if(QuadMode) {
+      // create medium node
+      double prm = l - du/2.;
+      gp_Pnt PM = Curve->Value(prm);
+      SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
+      meshDS->SetNodeOnEdge(NM, shapeID, prm);
+      SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
+      meshDS->SetMeshElementOnShape(edge, shapeID);
+    }
+    else {
+      SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
+      meshDS->SetMeshElementOnShape(edge, shapeID);
+    }
   }
   return true;
 }