Salome HOME
PAL13460 (PAL EDF 301 force the mesh to go through a point)
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index b3470ba4a9684bf67d982f604f4070e49a4bfaff..b35d55b0937da34dfe9ee4b395c2e884a0d30cab 100644 (file)
@@ -42,6 +42,7 @@
 #include "SMESH_subMesh.hxx"
 #include "SMESH_ControlsDef.hxx"
 #include "SMESH_MesherHelper.hxx"
+#include "SMESH_OctreeNode.hxx"
 
 #include "utilities.h"
 
@@ -95,6 +96,137 @@ myMesh( theMesh )
 {
 }
 
+//=======================================================================
+/*!
+ * \brief Add element
+ */
+//=======================================================================
+
+SMDS_MeshElement*
+SMESH_MeshEditor::AddElement(const vector<const SMDS_MeshNode*> & node,
+                             const SMDSAbs_ElementType            type,
+                             const bool                           isPoly,
+                             const int                            ID)
+{
+  SMDS_MeshElement* e = 0;
+  int nbnode = node.size();
+  SMESHDS_Mesh* mesh = GetMeshDS();
+  switch ( type ) {
+  case SMDSAbs_Edge:
+    if ( nbnode == 2 )
+      if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID);
+      else      e = mesh->AddEdge      (node[0], node[1] );
+    else if ( nbnode == 3 )
+      if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID);
+      else      e = mesh->AddEdge      (node[0], node[1], node[2] );
+    break;
+  case SMDSAbs_Face:
+    if ( !isPoly ) {
+      if      (nbnode == 3)
+        if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], ID);
+        else      e = mesh->AddFace      (node[0], node[1], node[2] );
+      else if (nbnode == 4) 
+        if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3], ID);
+        else      e = mesh->AddFace      (node[0], node[1], node[2], node[3] );
+      else if (nbnode == 6)
+        if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[3],
+                                          node[4], node[5], ID);
+        else      e = mesh->AddFace      (node[0], node[1], node[2], node[3],
+                                          node[4], node[5] );
+      else if (nbnode == 8)
+        if ( ID ) e = mesh->AddFaceWithID(node[0], node[1], node[2], node[2],
+                                          node[3], node[4], node[5], node[2], ID);
+        else      e = mesh->AddFace      (node[0], node[1], node[2], node[2],
+                                          node[3], node[4], node[5], node[2] );
+    } else {
+      if ( ID ) e = mesh->AddPolygonalFaceWithID(node, ID);
+      else      e = mesh->AddPolygonalFace      (node    );
+    }
+    break;
+  case SMDSAbs_Volume:
+    if ( !isPoly ) {
+      if      (nbnode == 4)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3], ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3] );
+      else if (nbnode == 5)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4] );
+      else if (nbnode == 6)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5] );
+      else if (nbnode == 8)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7], ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7] );
+      else if (nbnode == 10)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9] );
+      else if (nbnode == 13)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12],ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12] );
+      else if (nbnode == 15)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12],node[13],node[14],ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12],node[13],node[14] );
+      else if (nbnode == 20)
+        if ( ID ) e = mesh->AddVolumeWithID(node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12],node[13],node[14],node[15],
+                                            node[16],node[17],node[18],node[19],ID);
+        else      e = mesh->AddVolume      (node[0], node[1], node[2], node[3],
+                                            node[4], node[5], node[6], node[7],
+                                            node[8], node[9], node[10],node[11],
+                                            node[12],node[13],node[14],node[15],
+                                            node[16],node[17],node[18],node[19] );
+    }
+  }
+  return e;
+}
+
+//=======================================================================
+/*!
+ * \brief Add element
+ */
+//=======================================================================
+
+SMDS_MeshElement* SMESH_MeshEditor::AddElement(const vector<int> &       nodeIDs,
+                                               const SMDSAbs_ElementType type,
+                                               const bool                isPoly,
+                                               const int                 ID)
+{
+  vector<const SMDS_MeshNode*> nodes;
+  nodes.reserve( nodeIDs.size() );
+  vector<int>::const_iterator id = nodeIDs.begin();
+  while ( id != nodeIDs.end() ) {
+    if ( const SMDS_MeshNode* node = GetMeshDS()->FindNode( *id++ ))
+      nodes.push_back( node );
+    else
+      return 0;
+  }
+  return AddElement( nodes, type, isPoly, ID );
+}
+
 //=======================================================================
 //function : Remove
 //purpose  : Remove a node or an element.
@@ -217,19 +349,17 @@ int SMESH_MeshEditor::FindShape (const SMDS_MeshElement * theElem)
 
 //=======================================================================
 //function : IsMedium
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESH_MeshEditor::IsMedium(const SMDS_MeshNode*      node,
                                 const SMDSAbs_ElementType typeToCheck)
 {
   bool isMedium = false;
-  SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+  SMDS_ElemIteratorPtr it = node->GetInverseElementIterator(typeToCheck);
   while (it->more()) {
     const SMDS_MeshElement* elem = it->next();
     isMedium = elem->IsMediumNode(node);
-    if ( typeToCheck == SMDSAbs_All || elem->GetType() == typeToCheck )
-      break;
   }
   return isMedium;
 }
@@ -302,7 +432,7 @@ static bool GetNodesFromTwoTria(const SMDS_MeshElement * theTria1,
     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) 
+  // 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;
 }
@@ -339,7 +469,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
     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++ )
@@ -358,7 +488,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
       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++ ) {
@@ -379,14 +509,14 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
     aNodes[ sameInd[ iB ]] = aNodes[ i1 ];
 
     //MESSAGE( theTria1 << theTria2 );
-    
+
     GetMeshDS()->ChangeElementNodes( theTria1, aNodes, 3 );
     GetMeshDS()->ChangeElementNodes( theTria2, &aNodes[ 3 ], 3 );
-    
+
     //MESSAGE( theTria1 << theTria2 );
 
     return true;
-  
+
   } // end if(F1 && F2)
 
   // check case of quadratic faces
@@ -400,19 +530,19 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
   //       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  
+  //  4 +--+--+ 3
   //       8
-  
+
   const SMDS_MeshNode* N1 [6];
   const SMDS_MeshNode* N2 [6];
   if(!GetNodesFromTwoTria(theTria1,theTria2,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) 
+  // 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];
@@ -530,7 +660,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
       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;
@@ -546,7 +676,7 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
     GetMeshDS()->ChangeElementNodes( tr2, aNodes2, 3 );
 
     //MESSAGE( tr1 << tr2 );
-    
+
     return true;
   }
 
@@ -664,19 +794,19 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
   //       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  
+  //  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) 
+  // 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];
@@ -767,13 +897,13 @@ 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 );
 
     }
@@ -899,7 +1029,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
              aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
         {
           inFaceNode = aNodes[ i-1 ];
-        } 
+        }
       }
       // find middle point for (0,1,2,3)
       // and create a node in this point;
@@ -1030,10 +1160,10 @@ void SMESH_MeshEditor::RemoveElemFromGroups (const SMDS_MeshElement* removeelem,
                                              SMESHDS_Mesh *          aMesh)
 {
   const set<SMESHDS_GroupBase*>& groups = aMesh->GetGroups();
-  if (!groups.empty()) 
+  if (!groups.empty())
   {
     set<SMESHDS_GroupBase*>::const_iterator GrIt = groups.begin();
-    for (; GrIt != groups.end(); GrIt++) 
+    for (; GrIt != groups.end(); GrIt++)
     {
       SMESHDS_Group* grp = dynamic_cast<SMESHDS_Group*>(*GrIt);
       if (!grp || grp->IsEmpty()) continue;
@@ -1124,7 +1254,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet & theElems,
              aNodes[ i-1 ]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
         {
           inFaceNode = aNodes[ i-1 ];
-        } 
+        }
       }
 
       // find middle point for (0,1,2,3)
@@ -1522,7 +1652,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             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) 
+            // 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];
@@ -1567,7 +1697,7 @@ bool SMESH_MeshEditor::TriToQuad (TIDSortedElemSet &                   theElems,
             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) 
+            // 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];
@@ -2542,7 +2672,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
               gp_XY uv2 = helper.GetNodeUV( face, Ns[i+2], Ns[i] );
               gp_XY uv = ( uv1 + uv2 ) / 2.;
               gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
-              x = xyz.X(); y = xyz.Y(); z = xyz.Z(); 
+              x = xyz.X(); y = xyz.Y(); z = xyz.Z();
             }
             else {
               x = (Ns[i]->X() + Ns[i+2]->X())/2;
@@ -2559,7 +2689,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         }
       }
     }
-    
+
   } // loop on face ids
 
 }
@@ -2780,7 +2910,7 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
         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 ],
@@ -2844,7 +2974,7 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
         // 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];
@@ -2854,7 +2984,7 @@ static void sweepElement(SMESHDS_Mesh*                         aMesh,
         //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;
@@ -3192,7 +3322,8 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
                                      const gp_Ax1&      theAxis,
                                      const double       theAngle,
                                      const int          theNbSteps,
-                                     const double       theTol)
+                                     const double       theTol,
+                                     const bool         theMakeWalls)
 {
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
@@ -3291,14 +3422,15 @@ void SMESH_MeshEditor::RotationSweep(TIDSortedElemSet & theElems,
     sweepElement( aMesh, elem, newNodesItVec, newElemsMap[elem], theNbSteps, myLastCreatedElems );
   }
 
-  makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes, theElems, theNbSteps, myLastCreatedElems );
-
+  if ( theMakeWalls )
+    makeWalls( aMesh, mapNewNodes, newElemsMap, mapElemNewNodes,
+               theElems, theNbSteps, myLastCreatedElems );
 }
 
 
 //=======================================================================
 //function : CreateNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
                                                   const double y,
@@ -3330,7 +3462,7 @@ const SMDS_MeshNode* SMESH_MeshEditor::CreateNode(const double x,
       gp_Pnt P2(aN->X(),aN->Y(),aN->Z());
       if(P1.Distance(P2)<tolnode)
         return aN;
-    }    
+    }
   }
 
   // create new node and return it
@@ -3949,7 +4081,7 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
       if ( !theCopy && needReverse ) {
         SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
         while ( invElemIt->more() ) {
-          const SMDS_MeshElement* iel = invElemIt->next(); 
+          const SMDS_MeshElement* iel = invElemIt->next();
           inverseElemSet.insert( iel );
         }
       }
@@ -4115,7 +4247,7 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
     }
 
     // find transformed nodes
-    const SMDS_MeshNode* nodes[8];
+    vector<const SMDS_MeshNode*> nodes(nbNodes);
     int iNode = 0;
     SMDS_ElemIteratorPtr itN = elem->nodesIterator();
     while ( itN->more() ) {
@@ -4130,63 +4262,14 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
       continue; // not all nodes transformed
 
     if ( theCopy ) {
-      // add a new element
-      switch ( elemType ) {
-      case SMDSAbs_Edge:
-        if ( nbNodes == 2 )
-          myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ] ));
-        else
-          myLastCreatedElems.Append(aMesh->AddEdge( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
-        break;
-      case SMDSAbs_Face:
-        if ( nbNodes == 3 )
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] ));
-        else if(nbNodes==4)
-          myLastCreatedElems.Append(aMesh->AddFace( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ]));
-        else if(nbNodes==6)
-          myLastCreatedElems.Append(aMesh->AddFace(nodes[0], nodes[1], nodes[2], nodes[3],
-                                             nodes[4], nodes[5]));
-        else // nbNodes==8
-          myLastCreatedElems.Append(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 )
-          myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ] ));
-        else if ( nbNodes == 8 )
-          myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
-                                               nodes[ 4 ], nodes[ 5 ], nodes[ 6 ] , nodes[ 7 ]));
-        else if ( nbNodes == 6 )
-          myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
-                                               nodes[ 4 ], nodes[ 5 ]));
-        else if ( nbNodes == 5 )
-          myLastCreatedElems.Append(aMesh->AddVolume( nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] , nodes[ 3 ],
-                                               nodes[ 4 ]));
-        else if(nbNodes==10)
-          myLastCreatedElems.Append(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)
-          myLastCreatedElems.Append(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)
-          myLastCreatedElems.Append(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
-          myLastCreatedElems.Append(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:;
-      }
+      if ( SMDS_MeshElement* elem = AddElement( nodes, elem->GetType(), elem->IsPoly() ))
+        myLastCreatedElems.Append( elem );
     }
     else
     {
       // reverse element as it was reversed by transformation
       if ( nbNodes > 2 )
-        aMesh->ChangeElementNodes( elem, nodes, nbNodes );
+        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
     }
   }
 }
@@ -4194,7 +4277,8 @@ void SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 //=======================================================================
 //function : FindCoincidentNodes
 //purpose  : Return list of group of nodes close to each other within theTolerance
-//           Search among theNodes or in the whole mesh if theNodes is empty.
+//           Search among theNodes or in the whole mesh if theNodes is empty using
+//           an Octree algorithm
 //=======================================================================
 
 void SMESH_MeshEditor::FindCoincidentNodes (set<const SMDS_MeshNode*> & theNodes,
@@ -4204,48 +4288,17 @@ void SMESH_MeshEditor::FindCoincidentNodes (set<const SMDS_MeshNode*> & theNodes
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
 
-  double tol2 = theTolerance * theTolerance;
-
-  list<const SMDS_MeshNode*> nodes;
+  set<const SMDS_MeshNode*> nodes;
   if ( theNodes.empty() )
   { // get all nodes in the mesh
     SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator();
     while ( nIt->more() )
-      nodes.push_back( nIt->next() );
+      nodes.insert( nodes.end(),nIt->next());
   }
   else
-  {
-    nodes.insert( nodes.end(), theNodes.begin(), theNodes.end() );
-  }
+    nodes=theNodes;
+  SMESH_OctreeNode::FindCoincidentNodes ( nodes, &theGroupsOfNodes, theTolerance);
 
-  list<const SMDS_MeshNode*>::iterator it2, it1 = nodes.begin();
-  for ( ; it1 != nodes.end(); it1++ )
-  {
-    const SMDS_MeshNode* n1 = *it1;
-    gp_Pnt p1( n1->X(), n1->Y(), n1->Z() );
-
-    list<const SMDS_MeshNode*> * groupPtr = 0;
-    it2 = it1;
-    for ( it2++; it2 != nodes.end(); it2++ )
-    {
-      const SMDS_MeshNode* n2 = *it2;
-      gp_Pnt p2( n2->X(), n2->Y(), n2->Z() );
-      if ( p1.SquareDistance( p2 ) <= tol2 )
-      {
-        if ( !groupPtr ) {
-          theGroupsOfNodes.push_back( list<const SMDS_MeshNode*>() );
-          groupPtr = & theGroupsOfNodes.back();
-          groupPtr->push_back( n1 );
-        }
-        if(groupPtr->front()>n2)
-          groupPtr->push_front( n2 );
-        else
-          groupPtr->push_back( n2 );
-        it2 = nodes.erase( it2 );
-        it2--;
-      }
-    }
-  }
 }
 
 //=======================================================================
@@ -4557,7 +4610,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
         else
           isOk = false;
         break;
-      case 8: { 
+      case 8: {
         if(elem->IsQuadratic()) { // Quadratic quadrangle
           //   1    5    2
           //    +---+---+
@@ -5853,11 +5906,11 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     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;
@@ -5874,7 +5927,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
       if ( aShapeId && newElem )
         aMesh->SetMeshElementOnShape( newElem, aShapeId );
     }
-    
+
     // change nodes of theFace
     const SMDS_MeshNode* newNodes[ 4 ];
     newNodes[ 0 ] = linkNodes[ i1 ];
@@ -5899,7 +5952,7 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theFace,
     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
@@ -6086,9 +6139,9 @@ void SMESH_MeshEditor::UpdateVolumes (const SMDS_MeshNode*        theBetweenNode
 //function : ConvertElemToQuadratic
 //purpose  :
 //=======================================================================
-void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm,
-                                              SMESH_MesherHelper* theHelper,
-                                             const bool theForce3d)
+void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *   theSm,
+                                              SMESH_MesherHelper& theHelper,
+                                             const bool          theForce3d)
 {
   if( !theSm ) return;
   SMESHDS_Mesh* meshDS = GetMeshDS();
@@ -6096,67 +6149,63 @@ void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm,
   while(ElemItr->more())
   {
     const SMDS_MeshElement* elem = ElemItr->next();
-    if( !elem ) continue;
+    if( !elem || elem->IsQuadratic() ) continue;
 
     int id = elem->GetID();
     int nbNodes = elem->NbNodes();
     vector<const SMDS_MeshNode *> aNds (nbNodes);
-    
+
     for(int i = 0; i < nbNodes; i++)
     {
       aNds[i] = elem->GetNode(i);
     }
-
     SMDSAbs_ElementType aType = elem->GetType();
+
+    theSm->RemoveElement(elem);
+    meshDS->SMDS_Mesh::RemoveFreeElement(elem);
+
     const SMDS_MeshElement* NewElem = 0;
 
     switch( aType )
     {
     case SMDSAbs_Edge :
     {
-      meshDS->RemoveFreeElement(elem, theSm);  
-      NewElem = theHelper->AddQuadraticEdge(aNds[0], aNds[1], id, theForce3d);
+      NewElem = theHelper.AddEdge(aNds[0], aNds[1], id, theForce3d);
       break;
     }
     case SMDSAbs_Face :
     {
-      if(elem->IsQuadratic()) continue;
-
-      meshDS->RemoveFreeElement(elem, theSm);
       switch(nbNodes)
       {
       case 3:
-       NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
+       NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
        break;
       case 4:
-       NewElem = theHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+       NewElem = theHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
        break;
       default:
        continue;
       }
-      break;  
+      break;
     }
     case SMDSAbs_Volume :
     {
-      if( elem->IsQuadratic() ) continue;
-
-      meshDS->RemoveFreeElement(elem, theSm);
       switch(nbNodes)
       {
       case 4:
-       NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true);
+       NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], id, true);
        break;
       case 6:
-       NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true);
+       NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3], aNds[4], aNds[5], id, true);
        break;
       case 8:
-       NewElem = theHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
-                                      aNds[4], aNds[5], aNds[6], aNds[7], id, true);
+       NewElem = theHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
+                                      aNds[4], aNds[5], aNds[6], aNds[7], id, true);
        break;
       default:
        continue;
       }
-      break;  
+      break;
     }
     default :
       continue;
@@ -6166,6 +6215,8 @@ void SMESH_MeshEditor::ConvertElemToQuadratic(SMESHDS_SubMesh *theSm,
       AddToSameGroups( NewElem, elem, meshDS);
       theSm->AddElement( NewElem );
     }
+    if ( NewElem != elem )
+      RemoveElemFromGroups (elem, meshDS);
   }
 }
 
@@ -6177,23 +6228,23 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
 {
   SMESHDS_Mesh* meshDS = GetMeshDS();
 
-  SMESH_MesherHelper* aHelper = new SMESH_MesherHelper(*myMesh);
-  aHelper->SetKeyIsQuadratic( true );
+  SMESH_MesherHelper aHelper(*myMesh);
+  aHelper.SetIsQuadratic( true );
   const TopoDS_Shape& aShape = meshDS->ShapeToMesh();
 
   if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) )
   {
     SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape);
-    
+
     const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn();
     map < int, SMESH_subMesh * >::const_iterator itsub;
     for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++)
     {
       SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS();
-      aHelper->SetSubShape( (*itsub).second->GetSubShape() );
+      aHelper.SetSubShape( (*itsub).second->GetSubShape() );
       ConvertElemToQuadratic(sm, aHelper, theForce3d);
     }
-    aHelper->SetSubShape( aSubMesh->GetSubShape() );
+    aHelper.SetSubShape( aSubMesh->GetSubShape() );
     ConvertElemToQuadratic(aSubMesh->GetSubMeshDS(), aHelper, theForce3d);
   }
   else
@@ -6202,17 +6253,19 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
     while(aEdgeItr->more())
     {
       const SMDS_MeshEdge* edge = aEdgeItr->next();
-      if(edge)
+      if(edge && !edge->IsQuadratic())
       {
        int id = edge->GetID();
        const SMDS_MeshNode* n1 = edge->GetNode(0);
        const SMDS_MeshNode* n2 = edge->GetNode(1);
 
-       RemoveElemFromGroups (edge, meshDS);
        meshDS->SMDS_Mesh::RemoveFreeElement(edge);
 
-        const SMDS_QuadraticEdge* NewEdge = aHelper->AddQuadraticEdge(n1, n2, id, theForce3d);
-        AddToSameGroups(NewEdge, edge, meshDS);
+        const SMDS_MeshEdge* NewEdge = aHelper.AddEdge(n1, n2, id, theForce3d);
+        if ( NewEdge )
+          AddToSameGroups(NewEdge, edge, meshDS);
+        if ( NewEdge != edge )
+          RemoveElemFromGroups (edge, meshDS);
       }
     }
     SMDS_FaceIteratorPtr aFaceItr = meshDS->facesIterator();
@@ -6220,7 +6273,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
     {
       const SMDS_MeshFace* face = aFaceItr->next();
       if(!face || face->IsQuadratic() ) continue;
-      
+
       int id = face->GetID();
       int nbNodes = face->NbNodes();
       vector<const SMDS_MeshNode *> aNds (nbNodes);
@@ -6230,29 +6283,31 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
        aNds[i] = face->GetNode(i);
       }
 
-      RemoveElemFromGroups (face, meshDS); 
       meshDS->SMDS_Mesh::RemoveFreeElement(face);
 
       SMDS_MeshFace * NewFace = 0;
       switch(nbNodes)
       {
       case 3:
-       NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
+       NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], id, theForce3d);
        break;
       case 4:
-       NewFace = aHelper->AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
+       NewFace = aHelper.AddFace(aNds[0], aNds[1], aNds[2], aNds[3], id, theForce3d);
        break;
       default:
        continue;
       }
-      AddToSameGroups(NewFace, face, meshDS);
+      if ( NewFace )
+        AddToSameGroups(NewFace, face, meshDS);
+      if ( NewFace != face )
+        RemoveElemFromGroups (face, meshDS);
     }
     SMDS_VolumeIteratorPtr aVolumeItr = meshDS->volumesIterator();
     while(aVolumeItr->more())
     {
       const SMDS_MeshVolume* volume = aVolumeItr->next();
       if(!volume || volume->IsQuadratic() ) continue;
-      
+
       int id = volume->GetID();
       int nbNodes = volume->NbNodes();
       vector<const SMDS_MeshNode *> aNds (nbNodes);
@@ -6262,111 +6317,95 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
        aNds[i] = volume->GetNode(i);
       }
 
-      RemoveElemFromGroups (volume, meshDS);
       meshDS->SMDS_Mesh::RemoveFreeElement(volume);
 
       SMDS_MeshVolume * NewVolume = 0;
       switch(nbNodes)
       {
       case 4:
-       NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2],
-                                       aNds[3], id, true );
+       NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2],
+                                      aNds[3], id, true );
        break;
       case 6:
-       NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2],
-                                       aNds[3], aNds[4], aNds[5], id, true);
+       NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2],
+                                      aNds[3], aNds[4], aNds[5], id, true);
        break;
       case 8:
-       NewVolume = aHelper->AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
-                                      aNds[4], aNds[5], aNds[6], aNds[7], id, true);
+       NewVolume = aHelper.AddVolume(aNds[0], aNds[1], aNds[2], aNds[3],
+                                      aNds[4], aNds[5], aNds[6], aNds[7], id, true);
        break;
       default:
        continue;
       }
-      AddToSameGroups(NewVolume, volume, meshDS);
+      if ( NewVolume )
+        AddToSameGroups(NewVolume, volume, meshDS);
+      if ( NewVolume != volume )
+        RemoveElemFromGroups (volume, meshDS);
     }
   }
-  delete aHelper;
 }
 
 //=======================================================================
 //function : RemoveQuadElem
 //purpose  :
 //=======================================================================
-void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *theSm, 
+void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *    theSm,
                                      SMDS_ElemIteratorPtr theItr,
-                                     RemoveQuadNodeMap& theRemoveNodeMap)
+                                     const int            theShapeID)
 {
   SMESHDS_Mesh* meshDS = GetMeshDS();
   while( theItr->more() )
   {
     const SMDS_MeshElement* elem = theItr->next();
-    if( elem )
+    if( elem && elem->IsQuadratic())
     {
-      if( !elem->IsQuadratic() )
-        continue;
-      
       int id = elem->GetID();
-
-      int nbNodes = elem->NbNodes(), idx = 0;
-      vector<const SMDS_MeshNode *> aNds; 
+      int nbNodes = elem->NbNodes();
+      vector<const SMDS_MeshNode *> aNds, mediumNodes;
+      aNds.reserve( nbNodes );
+      mediumNodes.reserve( nbNodes );
 
       for(int i = 0; i < nbNodes; i++)
       {
        const SMDS_MeshNode* n = elem->GetNode(i);
 
        if( elem->IsMediumNode( n ) )
-       {
-         ItRemoveQuadNodeMap itRNM = theRemoveNodeMap.find( n );
-         if( itRNM == theRemoveNodeMap.end() )
-         {
-           theRemoveNodeMap.insert(RemoveQuadNodeMap::value_type( n,theSm ));
-         }
-       }
-       else 
+          mediumNodes.push_back( n );
+       else
          aNds.push_back( n );
       }
-
-      idx = aNds.size();
-      if( !idx ) continue;
-      SMDSAbs_ElementType aType = elem->GetType();      
+      if( aNds.empty() ) continue;
+      SMDSAbs_ElementType aType = elem->GetType();
 
       //remove old quadratic elements
-      meshDS->RemoveFreeElement( elem, theSm );
-
-      SMDS_MeshElement * NewElem = 0;
-      switch(aType)
-      {
-        case SMDSAbs_Edge:
-         NewElem = meshDS->AddEdgeWithID( aNds[0], aNds[1] ,id );
-         break;
-       case SMDSAbs_Face:
-         if( idx==3 ) NewElem = meshDS->AddFaceWithID( aNds[0],
-                                   aNds[1], aNds[2], id );
-         if( idx==4 ) NewElem = meshDS->AddFaceWithID( aNds[0],
-                                  aNds[1], aNds[2], aNds[3],id );
-         break;
-       case SMDSAbs_Volume:
-         if( idx==4 ) NewElem = meshDS->AddVolumeWithID( aNds[0],
-                                  aNds[1], aNds[2], aNds[3], id );
-         if( idx==6 ) NewElem = meshDS->AddVolumeWithID( aNds[0],
-                                  aNds[1], aNds[2], aNds[3],
-                                  aNds[4], aNds[5], id );
-         if( idx==8 ) NewElem = meshDS->AddVolumeWithID(aNds[0],
-                                  aNds[1], aNds[2], aNds[3],
-                                  aNds[4], aNds[5], aNds[6],
-                                  aNds[7] ,id );
-         break;
-       default:
-         break;
-      }
-
-      AddToSameGroups(NewElem, elem, meshDS);
-      if( theSm )
+      meshDS->SMDS_Mesh::RemoveFreeElement( elem );
+      if ( theSm )
+        theSm->RemoveElement( elem );
+
+      SMDS_MeshElement * NewElem = AddElement( aNds, aType, false, id );
+      if ( NewElem )
+        AddToSameGroups(NewElem, elem, meshDS);
+      if ( NewElem != elem )
+        RemoveElemFromGroups (elem, meshDS);
+      if( theSm && NewElem )
        theSm->AddElement( NewElem );
+
+      // remove medium nodes
+      vector<const SMDS_MeshNode*>::iterator nIt = mediumNodes.begin();
+      for ( ; nIt != mediumNodes.end(); ++nIt ) {
+        const SMDS_MeshNode* n = *nIt;
+        if ( n->NbInverseNodes() == 0 ) {
+          if ( n->GetPosition()->GetShapeId() != theShapeID )
+            meshDS->RemoveFreeNode( n, meshDS->MeshElements
+                                    ( n->GetPosition()->GetShapeId() ));
+          else
+            meshDS->RemoveFreeNode( n, theSm );
+       }
+      }
     }
   }
 }
+
 //=======================================================================
 //function : ConvertFromQuadratic
 //purpose  :
@@ -6374,37 +6413,28 @@ void SMESH_MeshEditor::RemoveQuadElem(SMESHDS_SubMesh *theSm,
 bool  SMESH_MeshEditor::ConvertFromQuadratic()
 {
   SMESHDS_Mesh* meshDS = GetMeshDS();
-  RemoveQuadNodeMap aRemoveNodeMap;
-
   const TopoDS_Shape& aShape = meshDS->ShapeToMesh();
 
   if ( !aShape.IsNull() && GetMesh()->GetSubMeshContaining(aShape) )
   {
     SMESH_subMesh *aSubMesh = GetMesh()->GetSubMeshContaining(aShape);
-    
+
     const map < int, SMESH_subMesh * >& aMapSM = aSubMesh->DependsOn();
     map < int, SMESH_subMesh * >::const_iterator itsub;
     for (itsub = aMapSM.begin(); itsub != aMapSM.end(); itsub++)
     {
       SMESHDS_SubMesh *sm = ((*itsub).second)->GetSubMeshDS();
       if( sm )
-       RemoveQuadElem( sm, sm->GetElements(), aRemoveNodeMap );
+       RemoveQuadElem( sm, sm->GetElements(), itsub->second->GetId() );
     }
     SMESHDS_SubMesh *Sm = aSubMesh->GetSubMeshDS();
     if( Sm )
-      RemoveQuadElem( Sm, Sm->GetElements(), aRemoveNodeMap );
+      RemoveQuadElem( Sm, Sm->GetElements(), aSubMesh->GetId() );
   }
   else
   {
     SMESHDS_SubMesh *aSM = 0;
-    RemoveQuadElem( aSM, meshDS->elementsIterator(), aRemoveNodeMap );
-  }
-
-  //remove all quadratic nodes 
-  ItRemoveQuadNodeMap itRNM = aRemoveNodeMap.begin();
-  for ( ; itRNM != aRemoveNodeMap.end(); itRNM++ ) 
-  {
-    meshDS->RemoveFreeNode( (*itRNM).first, (*itRNM).second  );        
+    RemoveQuadElem( aSM, meshDS->elementsIterator(), 0 );
   }
 
   return true;
@@ -7014,7 +7044,7 @@ struct TLink: public NLink
 
 //================================================================================
   /*!
-   * \brief Find corresponding nodes in two sets of faces 
+   * \brief Find corresponding nodes in two sets of faces
     * \param theSide1 - first face set
     * \param theSide2 - second first face
     * \param theFirstNode1 - a boundary node of set 1