Salome HOME
IPAL54384: TC8.5.0: SMESH: Regression delete groups with contents - exception
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 07385dc9062eae6641fe131e6a71ea4abaa154fe..bb3ecb80f37b8dc29965ab9416fb4c5cc062621f 100644 (file)
-//  SMESH SMDS : implementaion of Salome mesh data structure
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
-
-#include "utilities.h"
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMDS : implementation of Salome mesh data structure
+//
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+
 #include "SMDS_Mesh.hxx"
-#include "SMDS_VolumeOfNodes.hxx"
-#include "SMDS_VolumeOfFaces.hxx"
-#include "SMDS_FaceOfNodes.hxx"
-#include "SMDS_Tria3OfNodes.hxx"
-#include "SMDS_HexahedronOfNodes.hxx"
-#include "SMDS_FaceOfEdges.hxx"
+
+#include "SMDS_ElementFactory.hxx"
+#include "SMDS_ElementHolder.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMDS_SpacePosition.hxx"
+#include "SMDS_UnstructuredGrid.hxx"
+
+#include <utilities.h>
+
+#include <vtkUnstructuredGrid.h>
+//#include <vtkUnstructuredGridWriter.h>
+#include <vtkCell.h>
+#include <vtkUnsignedCharArray.h>
+#include <vtkCellLinks.h>
+#include <vtkIdList.h>
+
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+#include <boost/make_shared.hpp>
+
+#if !defined WIN32 && !defined __APPLE__
+#include <sys/sysinfo.h>
+#endif
+
+// number of added entities to check memory after
+#define CHECKMEMORY_INTERVAL 100000
+
+#define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
+
+int SMDS_Mesh::chunkSize = 1024;
+
+//================================================================================
+/*!
+ * \brief Raise an exception if free memory (ram+swap) too low
+ * \param doNotRaise - if true, suppres exception, just return free memory size
+ * \retval int - amount of available memory in MB or negative number in failure case
+ */
+//================================================================================
+
+int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
+{
+  return -1;
+#if !defined WIN32 && !defined __APPLE__
+  struct sysinfo si;
+  int err = sysinfo( &si );
+  if ( err )
+    return -1;
+
+  const unsigned long Mbyte = 1024 * 1024;
+
+  static int limit = -1;
+  if ( limit < 0 ) {
+    if ( si.totalswap == 0 )
+    {
+      int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
+      if (status >= 0 ) {
+        limit = WEXITSTATUS(status);
+      }
+      else {
+        double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
+        limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
+      }
+    }
+    if ( limit < 20 )
+      limit = 20;
+    else
+      limit = int ( limit * 1.5 );
+    MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
+  }
+
+  // compute separately to avoid overflow
+  int freeMb =
+    ( si.freeram  * si.mem_unit ) / Mbyte +
+    ( si.freeswap * si.mem_unit ) / Mbyte;
+
+  if ( freeMb > limit )
+    return freeMb - limit;
+
+  if ( doNotRaise )
+    return 0;
+
+  MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
+  throw std::bad_alloc();
+#else
+  return -1;
+#endif
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Create a new mesh object
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Mesh::SMDS_Mesh()
-       :myNodeIDFactory(new SMDS_MeshElementIDFactory()),
-       myElementIDFactory(new SMDS_MeshElementIDFactory()),
-       myHasConstructionEdges(false), myHasConstructionFaces(false),
-       myHasInverseElements(true)
+SMDS_Mesh::SMDS_Mesh():
+  myNodeFactory( new SMDS_NodeFactory( this )),
+  myCellFactory( new SMDS_ElementFactory( this )),
+  myParent(NULL),
+  myModified(false), myModifTime(0), myCompactTime(0),
+  xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
 {
+  myGrid = SMDS_UnstructuredGrid::New();
+  myGrid->setSMDS_mesh(this);
+  myGrid->Initialize();
+  myGrid->Allocate();
+  vtkPoints* points = vtkPoints::New();
+  // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+  // Use double type for storing coordinates of nodes instead of float.
+  points->SetDataType(VTK_DOUBLE);
+  points->SetNumberOfPoints( 0 );
+  myGrid->SetPoints( points );
+  points->Delete();
+  this->Modified();
+
+  // initialize static maps in SMDS_MeshCell, to be thread-safe
+  SMDS_MeshCell::InitStaticMembers();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -44,11 +149,10 @@ SMDS_Mesh::SMDS_Mesh()
 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
 /// (2003-09-08) of SMESH
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
-       :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
-       myElementIDFactory(parent->myElementIDFactory),
-       myHasConstructionEdges(false), myHasConstructionFaces(false),
-       myHasInverseElements(true)
+SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
+  myNodeFactory( new SMDS_NodeFactory( this )),
+  myCellFactory( new SMDS_ElementFactory( this )),
+  myParent(parent)
 {
 }
 
@@ -58,9 +162,9 @@ SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
 
 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
 {
-       SMDS_Mesh *submesh = new SMDS_Mesh(this);
-       myChildren.insert(myChildren.end(), submesh);
-       return submesh;
+  SMDS_Mesh *submesh = new SMDS_Mesh(this);
+  myChildren.insert(myChildren.end(), submesh);
+  return submesh;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -71,7 +175,7 @@ SMDS_Mesh *SMDS_Mesh::AddSubMesh()
 
 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
 {
-       return AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
+  return SMDS_Mesh::AddNodeWithID( x,y,z, myNodeFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -79,20 +183,104 @@ SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
 ///@param ID : The ID of the MeshNode to create
 ///@return : The created node or NULL if a node with this ID already exists
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
+SMDS_MeshNode * SMDS_Mesh::AddNodeWithID( double x, double y, double z, int ID )
+{
+  // find the MeshNode corresponding to ID
+  SMDS_MeshNode *node = myNodeFactory->NewNode( ID );
+  if ( node )
+  {
+    node->init( x, y, z );
+    myInfo.myNbNodes++;
+    myModified = true;
+    this->adjustBoundingBox(x, y, z);
+  }
+  return node;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
+{
+  const SMDS_MeshNode * node = myNodeFactory->FindNode(idnode);
+  if (!node) return NULL;
+  return SMDS_Mesh::Add0DElementWithID(node, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
+{
+  return SMDS_Mesh::Add0DElementWithID( node, myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Mesh0DElement and at it to the mesh
+/// @param idnode ID of the node
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
+{
+  if (!n) return 0;
+
+  if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+  if ( SMDS_MeshCell * cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_0D, /*nbNodes=*/1, n );
+    myInfo.myNb0DElements++;
+    return static_cast< SMDS_Mesh0DElement*> ( cell );
+  }
+
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID( int idnode, double diameter, int ID )
+{
+  const SMDS_MeshNode * node = myNodeFactory->FindNode( idnode );
+  if (!node) return NULL;
+  return SMDS_Mesh::AddBallWithID( node, diameter, ID );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
+{
+  return SMDS_Mesh::AddBallWithID(node, diameter, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Ball and at it to the mesh
+/// @param idnode ID of the node
+//  @param diameter ball diameter
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
 {
-       // find the MeshNode corresponding to ID
-       const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
+  if (!n) return 0;
 
-       if (node == NULL)
-       {
-               SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
-               myNodes.insert(node);
-               myNodeIDFactory->BindID(ID,node);
-               return node;
-       }
-       else
-               return NULL;
+  if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+  SMDS_BallElement* ball = static_cast< SMDS_BallElement*>( myCellFactory->NewElement( ID ));
+  if ( ball )
+  {
+    ball->init( n, diameter );
+    myInfo.myNbBalls++;
+  }
+  return ball;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -100,12 +288,12 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
 /// @return : The created MeshEdge
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID) 
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 {
-       SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       if((node1==NULL)||(node2==NULL)) return NULL;
-       return AddEdgeWithID(node1, node2, ID);
+  const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
+  const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
+  if(!node1 || !node2) return NULL;
+  return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -114,9 +302,9 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
-       const SMDS_MeshNode * node2)
+                                  const SMDS_MeshNode * node2)
 {
-       return AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddEdgeWithID(node1, node2, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -124,30 +312,23 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
 /// @param idnode1 ID of the first node
 /// @param idnode2 ID of the second node
 /// @param ID ID of the edge to create
-/// @return The created edge or NULL if an edge with this ID already exists or
+/// @return The created edge or NULL if an element with this ID already exists or
 /// if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
-               const SMDS_MeshNode * n2, int ID)
+                                        const SMDS_MeshNode * n2,
+                                        int                   ID)
 {
-       SMDS_MeshNode *node1,*node2;
-       node1=const_cast<SMDS_MeshNode*>(n1);
-       node2=const_cast<SMDS_MeshNode*>(n2);
+  if ( !n1 || !n2 ) return 0;
 
-       SMDS_MeshEdge * edge=new SMDS_MeshEdge(node1,node2);
-       if(myElementIDFactory->BindID(ID, edge))
-       {
-               node1->AddInverseElement(edge);
-               node2->AddInverseElement(edge);         
-               myEdges.insert(edge);
-               return edge;
-       } 
-       else
-       {
-               delete edge;
-               return NULL;
-       }
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Edge, /*nbNodes=*/2, n1, n2 );
+    myInfo.myNbEdges++;
+    return static_cast<SMDS_MeshEdge*>( cell );
+  }
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -156,81 +337,76 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2,
-       const SMDS_MeshNode * n3)
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3)
 {
-       return AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Add a quadrangle defined by its nodes IDs
+/// Add a triangle defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
 {
-       SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
-       return AddFaceWithID(node1, node2, node3, ID);  
+  const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
+  const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
+  const SMDS_MeshNode * node3 = myNodeFactory->FindNode(idnode3);
+  if(!node1 || !node2 || !node3) return NULL;
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Add a quadrangle defined by its nodes
+/// Add a triangle defined by its nodes
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(
-       const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2,
-       const SMDS_MeshNode * n3, int ID)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       SMDS_MeshFace * face=createTriangle(node1, node2, node3);
+  if ( !n1 || !n2 || !n3 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-       if(myElementIDFactory->BindID(ID, face))
-       {
-               node1->AddInverseElement(face);
-               node2->AddInverseElement(face);
-        node3->AddInverseElement(face);
-               return face;
-       }       
-       else
-       {
-               RemoveFace(face);
-               return NULL;
-       }
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Triangle, /*nbNodes=*/3, n1, n2, n3 );
+    myInfo.myNbTriangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Add a triangle defined by its nodes. An ID is automatically affected to the
+/// Add a quadrangle defined by its nodes. An ID is automatically affected to the
 /// created face
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2,
-       const SMDS_MeshNode * n3,
-       const SMDS_MeshNode * n4)
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4)
 {
-       return AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Add a quadrangle defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3,
-       int idnode4, int ID)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
+                                        int idnode2,
+                                        int idnode3,
+                                        int idnode4,
+                                        int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4;
-       node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
-       return AddFaceWithID(node1, node2, node3, node4, ID);   
+  const SMDS_MeshNode *node1, *node2, *node3, *node4;
+  node1 = myNodeFactory->FindNode(idnode1);
+  node2 = myNodeFactory->FindNode(idnode2);
+  node3 = myNodeFactory->FindNode(idnode3);
+  node4 = myNodeFactory->FindNode(idnode4);
+  if ( !node1 || !node2 || !node3 || !node4 ) return NULL;
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -238,157 +414,122 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2, const SMDS_MeshNode * n3,
-       const SMDS_MeshNode * n4, int ID)
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       node4=const_cast<SMDS_MeshNode*>(n4);
-       SMDS_MeshFace * face=createQuadrangle(node1, node2, node3, node4);
+  if ( !n1 || !n2 || !n3 || !n4 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-       if(myElementIDFactory->BindID(ID, face))
-       {
-               node1->AddInverseElement(face);
-               node2->AddInverseElement(face);
-        node3->AddInverseElement(face);
-        node4->AddInverseElement(face);
-               return face;
-       }       
-       else
-       {
-               RemoveFace(face);
-               return NULL;
-       }
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quadrangle, /*nbNodes=*/4, n1, n2, n3, n4 );
+    myInfo.myNbQuadrangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
-///@return The created tetrahedron 
+///Create a new tetrahedron and add it to the mesh.
+///@return The created tetrahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2, const SMDS_MeshNode * n3,
-       const SMDS_MeshNode * n4)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4)
 {
-       int ID = myElementIDFactory->GetFreeID();
-       SMDS_MeshVolume * v = AddVolumeWithID(n1, n2, n3, n4, ID);
-       if(v==NULL) myElementIDFactory->ReleaseID(ID);
-       return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, myCellFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
+///Create a new tetrahedron and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created tetrahedron or NULL if an edge with this ID already exists
+///@return The created tetrahedron or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
-       int idnode3, int idnode4, int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4;
-       node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4=NULL)) return NULL;
-       return AddVolumeWithID(node1, node2, node3, node4, ID);
+  const SMDS_MeshNode *node1, *node2, *node3, *node4;
+  node1 = myNodeFactory->FindNode(idnode1);
+  node2 = myNodeFactory->FindNode(idnode2);
+  node3 = myNodeFactory->FindNode(idnode3);
+  node4 = myNodeFactory->FindNode(idnode4);
+  if(!node1 || !node2 || !node3 || !node4) return NULL;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
+///Create a new tetrahedron and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created tetrahedron 
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(
-               const SMDS_MeshNode * n1,
-               const SMDS_MeshNode * n2,
-               const SMDS_MeshNode * n3,
-               const SMDS_MeshNode * n4, int ID)
-{
-       SMDS_MeshNode *node1, *node2, *node3, *node4;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       node4=const_cast<SMDS_MeshNode*>(n4);
-       SMDS_MeshVolume* volume;
-       if(hasConstructionFaces())
-       {
-               SMDS_MeshFace * f1=createTriangle(node1,node2,node3);
-               SMDS_MeshFace * f2=createTriangle(node1,node2,node4);
-               SMDS_MeshFace * f3=createTriangle(node1,node3,node4);
-               SMDS_MeshFace * f4=createTriangle(node2,node3,node4);
-               volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-               myVolumes.insert(volume);
-       }
-       else if(hasConstructionEdges())
-       {
-               MESSAGE("Error : Not implemented");
-               return NULL;
-       }
-       else
-       {
-               volume=new SMDS_VolumeOfNodes(node1,node2,node3,node4);
-               myVolumes.insert(volume);
-       }
-
-       if(myElementIDFactory->BindID(ID, volume))
-       {
-               node1->AddInverseElement(volume);
-               node2->AddInverseElement(volume);
-        node3->AddInverseElement(volume);
-               node4->AddInverseElement(volume);
-               return volume;
-       }       
-       else
-       {
-               RemoveVolume(volume);
-               return NULL;
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid and add it to the mesh. 
+///@return The created tetrahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 ) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Tetra, /*nbNodes=*/4, n1, n2, n3, n4 );
+    myInfo.myNbTetras++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
-///@return The created pyramid 
+///@return The created pyramid
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-       const SMDS_MeshNode * n2, const SMDS_MeshNode * n3,
-       const SMDS_MeshNode * n4, const SMDS_MeshNode * n5)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5)
 {
-       int ID = myElementIDFactory->GetFreeID();
-       SMDS_MeshVolume * v = AddVolumeWithID(n1, n2, n3, n4, n5, ID);
-       if(v==NULL) myElementIDFactory->ReleaseID(ID);
-       return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, myCellFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid and add it to the mesh. 
+///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
 ///@param ID The ID of the new volume
-///@return The created pyramid or NULL if a pyramid with this ID already exists
+///@return The created pyramid or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
-       int idnode3, int idnode4, int idnode5, int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
-       node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-       node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4=NULL)||
-               (node5=NULL))
-               return NULL;
-       return AddVolumeWithID(node1, node2, node3, node4, node5, ID);
+  const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
+  node1 = myNodeFactory->FindNode(idnode1);
+  node2 = myNodeFactory->FindNode(idnode2);
+  node3 = myNodeFactory->FindNode(idnode3);
+  node4 = myNodeFactory->FindNode(idnode4);
+  node5 = myNodeFactory->FindNode(idnode5);
+  if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
@@ -396,97 +537,68 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
 ///@return The created pyramid
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(
-               const SMDS_MeshNode * n1,
-               const SMDS_MeshNode * n2,
-               const SMDS_MeshNode * n3,
-               const SMDS_MeshNode * n4,
-               const SMDS_MeshNode * n5, int ID)
-{
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       node4=const_cast<SMDS_MeshNode*>(n4);
-       node5=const_cast<SMDS_MeshNode*>(n5);
-       SMDS_MeshVolume* volume;
-       if(hasConstructionFaces())
-       {
-               SMDS_MeshFace * f1=createQuadrangle(node1,node2,node3,node4);
-               SMDS_MeshFace * f2=createTriangle(node1,node2,node5);
-               SMDS_MeshFace * f3=createTriangle(node2,node3,node5);
-               SMDS_MeshFace * f4=createTriangle(node3,node4,node5);
-               volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-               myVolumes.insert(volume);
-       }
-       else if(hasConstructionEdges())
-       {
-               MESSAGE("Error : Not implemented");
-               return NULL;
-       }
-       else
-       {
-               volume=new SMDS_VolumeOfNodes(node1,node2,node3,node4,node5);
-               myVolumes.insert(volume);
-       }
-
-       if(myElementIDFactory->BindID(ID, volume))
-       {
-               node1->AddInverseElement(volume);
-               node2->AddInverseElement(volume);
-        node3->AddInverseElement(volume);
-               node4->AddInverseElement(volume);
-               node5->AddInverseElement(volume);
-               return volume;
-       }       
-       else
-       {
-               RemoveVolume(volume);
-               return NULL;
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new prism and add it to the mesh. 
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 ) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Pyramid, /*nbNodes=*/5, n1, n2, n3, n4, n5 );
+    myInfo.myNbPyramids++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
-///@return The created prism 
+///@return The created prism
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::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 * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6)
 {
-       int ID = myElementIDFactory->GetFreeID();
-       SMDS_MeshVolume * v = AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
-       if(v==NULL) myElementIDFactory->ReleaseID(ID);
-       return v;
+  int ID = myCellFactory->GetFreeID();
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new prism and add it to the mesh. 
+///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
 ///@param ID The ID of the new volume
-///@return The created prism or NULL if a prism with this ID already exists
+///@return The created prism or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
-       int idnode3, int idnode4, int idnode5, int idnode6, int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
-       node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-       node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
-       node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4=NULL)||
-               (node5==NULL)||(node6=NULL))
-               return NULL;
-       return AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
+  const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
+  node1 = myNodeFactory->FindNode(idnode1);
+  node2 = myNodeFactory->FindNode(idnode2);
+  node3 = myNodeFactory->FindNode(idnode3);
+  node4 = myNodeFactory->FindNode(idnode4);
+  node5 = myNodeFactory->FindNode(idnode5);
+  node6 = myNodeFactory->FindNode(idnode6);
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
@@ -494,271 +606,408 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
 ///@return The created prism
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(
-               const SMDS_MeshNode * n1,
-               const SMDS_MeshNode * n2,
-               const SMDS_MeshNode * n3,
-               const SMDS_MeshNode * n4,
-               const SMDS_MeshNode * n5,
-               const SMDS_MeshNode * n6, int ID)
-{
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       node4=const_cast<SMDS_MeshNode*>(n4);
-       node5=const_cast<SMDS_MeshNode*>(n5);
-       node6=const_cast<SMDS_MeshNode*>(n6);
-       SMDS_MeshVolume* volume;
-       if(hasConstructionFaces())
-       {
-               SMDS_MeshFace * f1=createTriangle(node1,node2,node3);
-               SMDS_MeshFace * f2=createTriangle(node4,node5,node6);
-               SMDS_MeshFace * f3=createQuadrangle(node1,node4,node5,node2);
-               SMDS_MeshFace * f4=createQuadrangle(node2,node5,node6,node3);
-               SMDS_MeshFace * f5=createQuadrangle(node3,node6,node4,node1);
-               volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
-               myVolumes.insert(volume);
-       }
-       else if(hasConstructionEdges())
-       {
-               MESSAGE("Error : Not implemented");
-               return NULL;
-       }
-       else
-       {
-               volume=new SMDS_VolumeOfNodes(node1,node2,node3,node4,node5,node6);
-               myVolumes.insert(volume);
-       }
-
-       if(myElementIDFactory->BindID(ID, volume))
-       {
-               node1->AddInverseElement(volume);
-               node2->AddInverseElement(volume);
-        node3->AddInverseElement(volume);
-               node4->AddInverseElement(volume);
-               node5->AddInverseElement(volume);
-               node6->AddInverseElement(volume);
-               return volume;
-       }       
-       else
-       {
-               RemoveVolume(volume);
-               return NULL;
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new hexahedron and add it to the mesh. 
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 ) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Penta, /*nbNodes=*/6, n1, n2, n3, n4, n5, n6 );
+    myInfo.myNbPrisms++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::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,
+                                      const SMDS_MeshNode * n9,
+                                      const SMDS_MeshNode * n10,
+                                      const SMDS_MeshNode * n11,
+                                      const SMDS_MeshNode * n12)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+                                    n7, n8, n9, n10, n11, n12,
+                                    myCellFactory->GetFreeID() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int idnode9,
+                                             int idnode10,
+                                             int idnode11,
+                                             int idnode12,
+                                             int ID)
+{
+  const SMDS_MeshNode *node1 = myNodeFactory->FindNode(idnode1);
+  const SMDS_MeshNode *node2 = myNodeFactory->FindNode(idnode2);
+  const SMDS_MeshNode *node3 = myNodeFactory->FindNode(idnode3);
+  const SMDS_MeshNode *node4 = myNodeFactory->FindNode(idnode4);
+  const SMDS_MeshNode *node5 = myNodeFactory->FindNode(idnode5);
+  const SMDS_MeshNode *node6 = myNodeFactory->FindNode(idnode6);
+  const SMDS_MeshNode *node7 = myNodeFactory->FindNode(idnode7);
+  const SMDS_MeshNode *node8 = myNodeFactory->FindNode(idnode8);
+  const SMDS_MeshNode *node9 = myNodeFactory->FindNode(idnode9);
+  const SMDS_MeshNode *node10 = myNodeFactory->FindNode(idnode10);
+  const SMDS_MeshNode *node11 = myNodeFactory->FindNode(idnode11);
+  const SMDS_MeshNode *node12 = myNodeFactory->FindNode(idnode12);
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+                                    node7, node8, node9, node10, node11, node12,
+                                    ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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_MeshNode * n9,
+                                            const SMDS_MeshNode * n10,
+                                            const SMDS_MeshNode * n11,
+                                            const SMDS_MeshNode * n12,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
+     !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
+    return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Hexagonal_Prism,
+                /*nbNodes=*/12, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12 );
+    myInfo.myNbHexPrism++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
-///@return The created hexahedron 
+///@return The created hexahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::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)
+                                      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)
 {
-       int ID = myElementIDFactory->GetFreeID();
-       SMDS_MeshVolume * v = AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
-       if(v==NULL) myElementIDFactory->ReleaseID(ID);
-       return v;
+  int ID = myCellFactory->GetFreeID();
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new hexahedron and add it to the mesh. 
+///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
 ///@param ID The ID of the new volume
-///@return The created hexahedron or NULL if an hexahedron with this ID already
+///@return The created hexahedron or NULL if an element with this ID already
 ///exists or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
-       int idnode3, int idnode4, int idnode5, int idnode6, int idnode7,
-       int idnode8, int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int ID)
 {
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
-       node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
-       node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
-       node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
-       node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-       node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
-       node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
-       node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
-       node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4=NULL)||
-               (node5==NULL)||(node6=NULL)||(node7==NULL)||(node8=NULL))
-               return NULL;
-       return AddVolumeWithID(node1, node2, node3, node4, node5, node6, node7,
-               node8, ID);
+  const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
+  node1 = myNodeFactory->FindNode(idnode1);
+  node2 = myNodeFactory->FindNode(idnode2);
+  node3 = myNodeFactory->FindNode(idnode3);
+  node4 = myNodeFactory->FindNode(idnode4);
+  node5 = myNodeFactory->FindNode(idnode5);
+  node6 = myNodeFactory->FindNode(idnode6);
+  node7 = myNodeFactory->FindNode(idnode7);
+  node8 = myNodeFactory->FindNode(idnode8);
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+                                    node7, node8, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
 ///@param ID The ID of the new volume
-///@return The created prism or NULL if an hexadron with this ID already exists
+///@return The created prism or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(
-               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, int ID)
-{
-       SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
-       node1=const_cast<SMDS_MeshNode*>(n1),
-       node2=const_cast<SMDS_MeshNode*>(n2),
-       node3=const_cast<SMDS_MeshNode*>(n3);
-       node4=const_cast<SMDS_MeshNode*>(n4);
-       node5=const_cast<SMDS_MeshNode*>(n5);
-       node6=const_cast<SMDS_MeshNode*>(n6);
-       node7=const_cast<SMDS_MeshNode*>(n7);
-       node8=const_cast<SMDS_MeshNode*>(n8);
-       SMDS_MeshVolume* volume;
-       if(hasConstructionFaces())
-       {
-               SMDS_MeshFace * f1=FindFaceOrCreate(node1,node2,node3,node4);
-               SMDS_MeshFace * f2=FindFaceOrCreate(node5,node6,node7,node8);
-               SMDS_MeshFace * f3=FindFaceOrCreate(node1,node4,node8,node5);
-               SMDS_MeshFace * f4=FindFaceOrCreate(node1,node2,node6,node5);
-               SMDS_MeshFace * f5=FindFaceOrCreate(node2,node3,node7,node6);
-               SMDS_MeshFace * f6=FindFaceOrCreate(node3,node4,node8,node7);
-               volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
-               myVolumes.insert(volume);
-       }
-       else if(hasConstructionEdges())
-       {
-               MESSAGE("Error : Not implemented");
-               return NULL;
-       }
-       else
-       {
-               volume=new SMDS_HexahedronOfNodes(node1,node2,node3,node4,node5,node6,
-                       node7,node8);
-               myVolumes.insert(volume);
-       }
-
-       if(myElementIDFactory->BindID(ID, volume))
-       {
-               node1->AddInverseElement(volume);
-               node2->AddInverseElement(volume);
-        node3->AddInverseElement(volume);
-               node4->AddInverseElement(volume);
-               node5->AddInverseElement(volume);
-               node6->AddInverseElement(volume);
-               node7->AddInverseElement(volume);
-               node8->AddInverseElement(volume);
-               return volume;
-       }       
-       else
-       {
-               RemoveVolume(volume);
-               return NULL;
-       }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Return the node whose ID is 'ID'.
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Hexa,
+                /*nbNodes=*/8, n1, n2, n3, n4, n5, n6, n7, n8 );
+    myInfo.myNbHexas++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
-const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
+/// Add a polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+                                                  const int               ID)
 {
-       return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
+  int nbNodes = nodes_ids.size();
+  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+  for (int i = 0; i < nbNodes; i++) {
+    nodes[i] = myNodeFactory->FindNode( nodes_ids[i] );
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a triangle and add it to the current mesh. This methode do not bind a
-///ID to the create triangle.
+/// Add a polygon defined by its nodes
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_MeshFace * SMDS_Mesh::createTriangle(SMDS_MeshNode * node1,
-       SMDS_MeshNode * node2, SMDS_MeshNode * node3)
+
+SMDS_MeshFace*
+SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+                                   const int                                 ID)
 {
-       if(hasConstructionEdges())
-       {
-               SMDS_MeshEdge *edge1, *edge2, *edge3;
-               edge1=FindEdgeOrCreate(node1,node2);
-               edge2=FindEdgeOrCreate(node2,node3);
-               edge3=FindEdgeOrCreate(node3,node1);
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-               SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
-               myFaces.insert(face);
-               return face;
-       }
-       else
-       {
-               SMDS_MeshFace * face = new SMDS_Tria3OfNodes(node1,node2,node3);
-               myFaces.insert(face);
-               return face;
-       }
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Polygon, nodes );
+    myInfo.myNbPolygons++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a quadrangle and add it to the current mesh. This methode do not bind
-///a ID to the create triangle.
+/// Add a polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_MeshFace * SMDS_Mesh::createQuadrangle(SMDS_MeshNode * node1,
-       SMDS_MeshNode * node2, SMDS_MeshNode * node3, SMDS_MeshNode * node4)
+
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
 {
-       if(hasConstructionEdges())
-       {
-               SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
-               edge1=FindEdgeOrCreate(node1,node2);
-               edge2=FindEdgeOrCreate(node2,node3);
-               edge3=FindEdgeOrCreate(node3,node4);
-               edge4=FindEdgeOrCreate(node4,node1);
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
 
-               SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
-               myFaces.insert(face);
-               return face;
-       }
-       else
-       {
-               SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
-               myFaces.insert(face);
-               return face;
-       }
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+                                                      const int                ID)
+{
+  std::vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
+  for ( size_t i = 0; i < nodes.size(); i++) {
+    nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Remove a node and all the elements which own this node
+/// Add a quadratic polygon defined by its nodes
 ///////////////////////////////////////////////////////////////////////////////
 
-void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
+SMDS_MeshFace*
+SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+                                       const int                                 ID)
+{
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Polygon, nodes );
+    myInfo.myNbQuadPolygons++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
 {
-       RemoveElement(node, true);
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Remove an edge and all the elements which own this edge
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created volume or NULL if an element with this ID already exists
+/// or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
+SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int> & nodes_ids,
+                                                        const std::vector<int> & quantities,
+                                                        const int                ID)
 {
-       RemoveElement(edge,true);
+  int nbNodes = nodes_ids.size();
+  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+  for (int i = 0; i < nbNodes; i++) {
+    nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Remove an face and all the elements which own this face
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created  volume
 ///////////////////////////////////////////////////////////////////////////////
 
-void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
+SMDS_MeshVolume*
+SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                      const std::vector<int>                 & quantities,
+                                      const int                           ID)
 {
-       RemoveElement(face, true);
+  if ( nodes.empty() || quantities.empty() )
+    return NULL;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    SMDS_MeshVolume* volume = static_cast<SMDS_MeshVolume*>( cell );
+    volume->init( nodes, quantities );
+    myInfo.myNbPolyhedrons++;
+    return volume;
+  }
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Remove a volume
+/// Create a new polyhedral volume and add it to the mesh.
+/// @return The created  volume
 ///////////////////////////////////////////////////////////////////////////////
 
-void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
+SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
+(const std::vector<const SMDS_MeshNode*> & nodes,
+ const std::vector<int>                  & quantities)
 {
-       RemoveElement(volume, true);
+  int ID = myCellFactory->GetFreeID();
+  return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
+}
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+  SMDS_MeshCell*   cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
+  SMDS_MeshVolume * vol = static_cast<SMDS_MeshVolume*>( cell );
+  vol->init( vtkNodeIds );
+  myInfo.add( cell );
+  return vol;
+}
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+  SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
+  SMDS_MeshFace *   f = static_cast<SMDS_MeshFace*>( cell );
+  f->init( vtkNodeIds );
+  myInfo.add( cell );
+  return f;
+}
+
+//=======================================================================
+//function : MoveNode
+//purpose  : 
+//=======================================================================
+
+void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
+{
+  SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
+  node->setXYZ(x,y,z);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose SMDS ID is 'ID'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
+{
+  return myNodeFactory->FindNode( ID );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose VTK ID is 'vtkId'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
+{
+  return myNodeFactory->FindNode( vtkId + 1 );
+}
+
+const SMDS_MeshElement * SMDS_Mesh::FindElementVtk(int IDelem) const
+{
+  return myCellFactory->FindElement( FromVtkToSmds( IDelem ));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a node and all the elements which own this node
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
+{
+  RemoveElement(node, true);
 }
 
 //=======================================================================
@@ -768,8 +1017,8 @@ void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 
 bool SMDS_Mesh::RemoveFromParent()
 {
-       if (myParent==NULL) return false;
-       else return (myParent->RemoveSubMesh(this));
+  if (myParent==NULL) return false;
+  else return (myParent->RemoveSubMesh(this));
 }
 
 //=======================================================================
@@ -779,82 +1028,135 @@ bool SMDS_Mesh::RemoveFromParent()
 
 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
 {
-       bool found = false;
+  bool found = false;
 
-       list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
-       for (; itmsh!=myChildren.end() && !found; itmsh++)
-       {
-               SMDS_Mesh * submesh = *itmsh;
-               if (submesh == aMesh)
-               {
-                       found = true;
-                       myChildren.erase(itmsh);
-               }
-       }
+  std::list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+  for (; itmsh!=myChildren.end() && !found; itmsh++)
+  {
+    SMDS_Mesh * submesh = *itmsh;
+    if (submesh == aMesh)
+    {
+      found = true;
+      myChildren.erase(itmsh);
+    }
+  }
 
-       return found;
+  return found;
 }
 
-
 //=======================================================================
-//function : FindEdge
+//function : ChangeElementNodes
 //purpose  :
 //=======================================================================
 
-const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
+bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
+                                   const SMDS_MeshNode    * nodes[],
+                                   const int                nbnodes)
+{
+  // keep current nodes of element
+  std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
+
+  // change nodes
+  bool Ok = false;
+  if ( SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element))
+    Ok = cell->ChangeNodes(nodes, nbnodes);
+
+  if ( Ok )
+    setMyModified();
+
+  if ( Ok && GetGrid()->HasLinks() ) // update InverseElements
+  {
+    std::set<const SMDS_MeshNode*>::iterator it;
+
+    // AddInverseElement to new nodes
+    for ( int i = 0; i < nbnodes; i++ ) {
+      it = oldNodes.find( nodes[i] );
+      if ( it == oldNodes.end() )
+        // new node
+        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( element );
+      else
+        // remove from oldNodes a node that remains in elem
+        oldNodes.erase( it );
+    }
+    // RemoveInverseElement from the nodes removed from elem
+    for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
+    {
+      SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
+      n->RemoveInverseElement( element );
+    }
+  }
+
+  return Ok;
+}
+
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
+{
+  if (!node) return 0;
+  const SMDS_Mesh0DElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->NbNodes() == 1) {
+      toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
+    }
+  }
+  return toReturn;
+}
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
+{
+  if (!node) return 0;
+  const SMDS_BallElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->GetGeomType() == SMDSGeom_BALL)
+      toReturn = static_cast<const SMDS_BallElement*>(e);
+  }
+  return toReturn;
+}
+
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
+                                         const SMDS_MeshNode * node2)
 {
-       const SMDS_MeshNode * node1=FindNode(idnode1);
-       const SMDS_MeshNode * node2=FindNode(idnode2);
-       if((node1==NULL)||(node2==NULL)) return NULL;
-       return FindEdge(node1,node2);
+  if ( !node1 ) return 0;
+  const SMDS_MeshEdge * toReturn=NULL;
+  SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
+      toReturn = static_cast<const SMDS_MeshEdge*>( e );
+      break;
+    }
+  }
+  return toReturn;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-///
-///////////////////////////////////////////////////////////////////////////////
-//#include "Profiler.h"
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
-       const SMDS_MeshNode * node2) const
-{
-       const SMDS_MeshEdge * toReturn=NULL;
-       //PROFILER_Init();
-       //PROFILER_Set();
-       SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->edgesIterator();
-       //PROFILER_Get(0);
-       //PROFILER_Set();
-       while(it1->more())
-       {
-               const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *>
-                       (it1->next());
-               SMDS_Iterator<const SMDS_MeshElement *>* it2=e->nodesIterator();
-               while(it2->more())
-               {
-                       if(it2->next()->GetID()==node2->GetID())
-                       {
-                               toReturn=e;
-                               break;
-                       }
-               }
-               delete it2;
-       }
-       //PROFILER_Get(1);
-       delete it1;
-       return toReturn;
-}
-
-
-SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
-       const SMDS_MeshNode * node2) 
-{
-       SMDS_MeshEdge * toReturn=NULL;
-       toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
-       if(toReturn==NULL)      
-       {
-               toReturn=new SMDS_MeshEdge(const_cast<SMDS_MeshNode*>(node1),
-                       const_cast<SMDS_MeshNode*>(node2));
-               myEdges.insert(toReturn);
-       } 
-       return toReturn;
+                                         const SMDS_MeshNode * node2,
+                                         const SMDS_MeshNode * node3)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshEdge *> (e);
+    }
+  }
+  return 0;
 }
 
 //=======================================================================
@@ -862,40 +1164,31 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
 //purpose  :
 //=======================================================================
 
-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);
-       const SMDS_MeshFace * face;
-       const SMDS_MeshElement * node;
-       bool node2found, node3found;
-       if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
-
-       SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->facesIterator();
-       while(it1->more())
-       {
-               face=static_cast<const SMDS_MeshFace*>(it1->next());
-               if(face->NbNodes()!=3) continue;
-               SMDS_Iterator<const SMDS_MeshElement *>* it2=face->nodesIterator();
-               node2found=false;
-               node3found=false;
-               while(it2->more())
-               {
-                       node=it2->next();
-                       if(node->GetID()==idnode2) node2found=true;
-                       if(node->GetID()==idnode3) node3found=true;
-               }
-               delete it2;
-               if(node2found&&node3found)
-               {
-                       delete it1;
-                       return face;
-               }
-       }
-       delete it1;
-       return NULL;
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
 }
 
 //=======================================================================
@@ -903,195 +1196,248 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
 //purpose  :
 //=======================================================================
 
-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_MeshFace* SMDS_Mesh::FindFace(
-               const SMDS_MeshNode *node1,
-               const SMDS_MeshNode *node2,
-               const SMDS_MeshNode *node3,
-               const SMDS_MeshNode *node4) const
-{
-       const SMDS_MeshFace * face;
-       const SMDS_MeshElement * node;
-       bool node2found, node3found, node4found;
-       SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->facesIterator();
-       while(it1->more())
-       {
-               face=static_cast<const SMDS_MeshFace *>(it1->next());
-               if(face->NbNodes()!=4) continue;
-               SMDS_Iterator<const SMDS_MeshElement *>* 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;
-               }
-               delete it2;
-               if(node2found&&node3found&&node4found)
-               {
-                       delete it1;
-                       return face;
-               }
-       }
-       delete it1;
-       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 * toReturn=NULL;
-       toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
-       if(toReturn==NULL)      
-       {
-               toReturn=createQuadrangle(
-                       const_cast<SMDS_MeshNode *>(node1),
-                       const_cast<SMDS_MeshNode *>(node2),
-                       const_cast<SMDS_MeshNode *>(node3),
-                       const_cast<SMDS_MeshNode *>(node4)
-               );
-       } 
-       return toReturn;
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3,
+                                         const SMDS_MeshNode *node4)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 4 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
 }
 
 //=======================================================================
-//function : FindElement
-//purpose  :
+//function : FindFace
+//purpose  :quadratic triangle
 //=======================================================================
 
-const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
-{
-       return myElementIDFactory->MeshElement(IDelem);
+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)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 6 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
 }
 
+
 //=======================================================================
-//function : DumpNodes
-//purpose  : 
+//function : FindFace
+//purpose  : quadratic quadrangle
 //=======================================================================
 
-void SMDS_Mesh::DumpNodes() const
-{
-       MESSAGE("dump nodes of mesh : ");
-       SMDS_Iterator<const SMDS_MeshNode *> * itnode=nodesIterator();
-       while(itnode->more()) MESSAGE(itnode->next());
-       delete itnode;
+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)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 8 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 &&
+            n!=node7 &&
+            n!=node8 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
 }
 
+
 //=======================================================================
-//function : DumpEdges
-//purpose  : 
+//function : FindElement
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::DumpEdges() const
+const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 {
-       MESSAGE("dump edges of mesh : ");
-       SMDS_Iterator<const SMDS_MeshEdge *> * itedge=edgesIterator();
-       while(itedge->more()) MESSAGE(itedge->next());
-       delete itedge;
+  return myCellFactory->FindElement( IDelem );
 }
 
 //=======================================================================
-//function : DumpFaces
-//purpose  : 
+//function : FindFace
+//purpose  : find polygon
 //=======================================================================
 
-void SMDS_Mesh::DumpFaces() const
-{
-       MESSAGE("dump faces of mesh : ");
-       SMDS_Iterator<const SMDS_MeshFace *> * itface=facesIterator();
-       while(itface->more()) MESSAGE(itface->next());
-       delete itface;
-}
 
-//=======================================================================
-//function : DumpVolumes
-//purpose  : 
-//=======================================================================
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const std::vector<const SMDS_MeshNode *>& nodes)
+{
+  return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
+}
+
+
+//================================================================================
+/*!
+ * \brief Return element based on all given nodes
+ *  \param nodes - node of element
+ *  \param type - type of element
+ *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
+ *  \retval const SMDS_MeshElement* - found element or NULL
+ */
+//================================================================================
+
+const SMDS_MeshElement* SMDS_Mesh::FindElement (const std::vector<const SMDS_MeshNode *>& nodes,
+                                                const SMDSAbs_ElementType            type,
+                                                const bool                           noMedium)
+{
+  if ( nodes.size() > 0 && nodes[0] )
+  {
+    SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
+    while (itF->more())
+    {
+      const SMDS_MeshElement* e = itF->next();
+      int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
+      if ( nbNodesToCheck == (int)nodes.size() )
+      {
+        for ( size_t i = 1; e && i < nodes.size(); ++i )
+        {
+          int nodeIndex = e->GetNodeIndex( nodes[ i ]);
+          if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
+            e = 0;
+        }
+        if ( e )
+          return e;
+      }
+    }
+  }
+  return NULL;
+}
+
+//================================================================================
+/*!
+ * \brief Return elements including all given nodes
+ *  \param [in] nodes - nodes to find elements around
+ *  \param [out] foundElems - the found elements
+ *  \param [in] type - type of elements to find
+ *  \return int - a number of found elements
+ */
+//================================================================================
+
+int SMDS_Mesh::GetElementsByNodes(const std::vector<const SMDS_MeshNode *>& nodes,
+                                  std::vector<const SMDS_MeshElement *>&    foundElems,
+                                  const SMDSAbs_ElementType                 type)
+{
+  // chose a node with minimal number of inverse elements
+  const SMDS_MeshNode* n0 = nodes[0];
+  int minNbInverse = n0 ? n0->NbInverseElements( type ) : 1000;
+  for ( size_t i = 1; i < nodes.size(); ++i )
+    if ( nodes[i] && nodes[i]->NbInverseElements( type ) < minNbInverse )
+    {
+      n0 = nodes[i];
+      minNbInverse = n0->NbInverseElements( type );
+    }
+
+  foundElems.clear();
+  if ( n0 )
+  {
+    foundElems.reserve( minNbInverse );
+    SMDS_ElemIteratorPtr eIt = n0->GetInverseElementIterator( type );
+    while ( eIt->more() )
+    {
+      const SMDS_MeshElement* e = eIt->next();
+      bool includeAll = true;
+      for ( size_t i = 0; i < nodes.size() &&  includeAll; ++i )
+        if ( nodes[i] != n0 && e->GetNodeIndex( nodes[i] ) < 0 )
+          includeAll = false;
+      if ( includeAll )
+        foundElems.push_back( e );
+    }
+  }
+  return foundElems.size();
+}
 
-void SMDS_Mesh::DumpVolumes() const
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of nodes
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbNodes() const
 {
-       MESSAGE("dump volumes of mesh : ");
-       SMDS_Iterator<const SMDS_MeshVolume *> * itvol=volumesIterator();
-       while(itvol->more()) MESSAGE(itvol->next());
-       delete itvol;
+  return myInfo.NbNodes();
 }
 
-//=======================================================================
-//function : DebugStats
-//purpose  : 
-//=======================================================================
-
-void SMDS_Mesh::DebugStats() const
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbElements() const
 {
-       MESSAGE("Debug stats of mesh : ");
-
-       MESSAGE("===== NODES ====="<<NbNodes());
-       MESSAGE("===== EDGES ====="<<NbEdges());
-       MESSAGE("===== FACES ====="<<NbFaces());
-       MESSAGE("===== VOLUMES ====="<<NbVolumes());
-
-       MESSAGE("End Debug stats of mesh ");
-
-       //#ifdef DEB
-       
-       SMDS_Iterator<const SMDS_MeshNode *> * itnode=nodesIterator();
-       int sizeofnodes = 0;
-       int sizeoffaces = 0;
-
-       while(itnode->more())
-       {
-               const SMDS_MeshNode *node = itnode->next();
-
-               sizeofnodes += sizeof(*node);
-               
-               SMDS_Iterator<const SMDS_MeshElement *> * it=
-                       node->GetInverseElementIterator();
-               while(it->more())
-               {
-                       const SMDS_MeshElement *me = it->next();
-                       sizeofnodes += sizeof(me);
-               }
-               delete it;
-
-       }
-       delete itnode;
-       SMDS_Iterator<const SMDS_MeshFace*>* itface=facesIterator();
-       
-       while(itface->more())
-       {
-               const SMDS_MeshElement *face = itface->next();          
-               sizeoffaces += sizeof(*face);
-
-       }
-       MESSAGE("total size of node elements = " << sizeofnodes);;
-       MESSAGE("total size of face elements = " << sizeoffaces);;
-
-       //#endif
-
+  return myInfo.NbElements();
+}
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::Nb0DElements() const
+{
+  return myInfo.Nb0DElements();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return the number of nodes
+/// Return the number of 0D elements
 ///////////////////////////////////////////////////////////////////////////////
-int SMDS_Mesh::NbNodes() const
+int SMDS_Mesh::NbBalls() const
 {
-       return myNodes.size();
+  return myInfo.NbBalls();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1099,7 +1445,7 @@ int SMDS_Mesh::NbNodes() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbEdges() const
 {
-       return myEdges.size();
+  return myInfo.NbEdges();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1107,7 +1453,7 @@ int SMDS_Mesh::NbEdges() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbFaces() const
 {
-       return myFaces.size();
+  return myInfo.NbFaces();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1115,17 +1461,16 @@ int SMDS_Mesh::NbFaces() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbVolumes() const
 {
-       return myVolumes.size();
+  return myInfo.NbVolumes();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return the number of child mesh of this mesh.
-/// Note that the tree structure of SMDS_Mesh seems to be unused in this version
-/// (2003-09-08) of SMESH
+/// Note that the tree structure of SMDS_Mesh is unused in SMESH
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbSubMesh() const
 {
-       return myChildren.size();
+  return myChildren.size();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1134,383 +1479,270 @@ int SMDS_Mesh::NbSubMesh() const
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_Mesh::~SMDS_Mesh()
 {
-       if(myParent==NULL)
-       {
-               delete myNodeIDFactory;
-               delete myElementIDFactory;
-       }
+  std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  while(itc!=myChildren.end())
+  {
+    delete *itc;
+    itc++;
+  }
+
+  delete myNodeFactory;
+  delete myCellFactory;
+
+  myGrid->Delete();
+}
+
+//================================================================================
+/*!
+ * \brief Clear all data
+ */
+//================================================================================
+
+void SMDS_Mesh::Clear()
+{
+  std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
+  for ( ; holder != myElemHolders.end(); ++holder )
+    (*holder)->clear();
 
-       list<SMDS_Mesh*>::iterator itc=myChildren.begin();
-       while(itc!=myChildren.end())
-       {
-               delete *itc;
-               itc++;
-       }
-       
-       SMDS_Iterator<const SMDS_MeshNode*> * itn=nodesIterator();
-       while(itn->more())
-       {
-               delete itn->next();
-       }
-       delete itn;
+  myNodeFactory->Clear();
+  myCellFactory->Clear();
 
-       set<SMDS_MeshEdge*>::iterator ite=myEdges.begin();
-       while(ite!=myEdges.end())
-       {
-               delete *ite;
-               ite++;
-       }
+  std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  while(itc!=myChildren.end())
+    (*itc)->Clear();
 
-       set<SMDS_MeshFace*>::iterator itf=myFaces.begin();
-       while(itf!=myFaces.end())
-       {
-               delete *itf;
-               itf++;
-       }
+  myModified = false;
+  myModifTime++;
+  xmin = 0; xmax = 0;
+  ymin = 0; ymax = 0;
+  zmin = 0; zmax = 0;
 
-       set<SMDS_MeshVolume*>::iterator itv=myVolumes.begin();
-       while(itv!=myVolumes.end())
-       {
-               delete *itv;
-               itv++;
-       }
+  myInfo.Clear();
 
+  myGrid->Initialize();
+  myGrid->Allocate();
+  vtkPoints* points = vtkPoints::New();
+  // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+  // using double type for storing coordinates of nodes instead float.
+  points->SetDataType(VTK_DOUBLE);
+  points->SetNumberOfPoints( 0 );
+  myGrid->SetPoints( points );
+  points->Delete();
+  myGrid->DeleteLinks();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return true if this mesh create faces with edges.
-/// A false returned value mean that faces are created with nodes. A concequence
-/// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
+/// Return an iterator on nodes of the current mesh factory
 ///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::hasConstructionEdges()
+
+SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
 {
-       return myHasConstructionEdges;
+  return myNodeFactory->GetIterator< SMDS_NodeIterator >( new SMDS_MeshElement::NonNullFilter );
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Return true if this mesh create volumes with faces
-/// A false returned value mean that volumes are created with nodes or edges.
-/// (see hasConstructionEdges)
-/// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
-/// unavailable.
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::hasConstructionFaces()
+SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
 {
-       return myHasConstructionFaces;
+  return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
+                                                          myInfo.NbElements( type ));
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Return true if nodes are linked to the finit elements, they are belonging to.
-/// Currently, It always return true.
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::hasInverseElements()
+SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
 {
-       return myHasInverseElements;
+  if ( type == SMDSEntity_Node )
+  {
+    return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
+  }
+  return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
+                                                        myInfo.NbElements( type ));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating construction edges (see hasConstructionEdges)
-/// @param b true to have construction edges, else false.
+/// Return an iterator on elements of the current mesh factory
 ///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setConstructionEdges(bool b)
+SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 {
-       myHasConstructionEdges=b;
+  typedef SMDS_ElemIterator TIterator;
+  switch ( type ) {
+
+  case SMDSAbs_All:
+    return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
+
+  case SMDSAbs_Node:
+    return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
+
+  default:
+    return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
+                                                    myInfo.NbElements( type ));
+  }
+  return SMDS_ElemIteratorPtr();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating construction faces (see hasConstructionFaces)
-/// @param b true to have construction faces, else false.
+///Return an iterator on edges of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setConstructionFaces(bool b)
+
+SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
 {
-        myHasConstructionFaces=b;
+  typedef SMDS_EdgeIterator TIterator;
+  return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
+                                                  myInfo.NbEdges());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating link from nodes to elements (see hasInverseElements)
-/// @param b true to link nodes to elements, else false.
+///Return an iterator on faces of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setInverseElements(bool b)
+
+SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
 {
-       if(!b) MESSAGE("Error : inverseElement=false not implemented");
-       myHasInverseElements=b;
+  typedef SMDS_FaceIterator TIterator;
+  return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
+                                                  myInfo.NbFaces());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return an iterator on nodes of the current mesh. Once used this iterator
-/// must be free by the caller
+///Return an iterator on volumes of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Iterator<const SMDS_MeshNode *> * SMDS_Mesh::nodesIterator() const
-{
-       class MyIterator:public SMDS_Iterator<const SMDS_MeshNode*>
-       {
-               const SetOfNodes& mySet;
-               SetOfNodes::iterator myIterator;
-         public:
-               MyIterator(const SetOfNodes& s):mySet(s)
-               {
-                       myIterator=mySet.begin();
-               }
-
-               bool more()
-               {
-                       return myIterator!=mySet.end();
-               }
 
-               const SMDS_MeshNode* next()
-               {
-                       const SMDS_MeshNode* current=*myIterator;
-                       myIterator++;
-                       return current; 
-               }       
-       };
-       return new MyIterator(myNodes);
+SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
+{
+  typedef SMDS_VolumeIterator TIterator;
+  return
+    myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
+                                             myInfo.NbVolumes());
 }
 
-///////////////////////////////////////////////////////////////////////////////
-///Return an iterator on volumes of the current mesh. Once used this iterator
-///must be free by the caller
-///////////////////////////////////////////////////////////////////////////////
-SMDS_Iterator<const SMDS_MeshEdge *> * SMDS_Mesh::edgesIterator() const
+SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
 {
-       class MyIterator:public SMDS_Iterator<const SMDS_MeshEdge*>
-       {
-               const SetOfEdges& mySet;
-               const SMDS_MeshEdge * myEdge;
-               SetOfEdges::iterator myIterator;
-         public:
-               MyIterator(const SetOfEdges& s):mySet(s)
-               {
-                       myIterator=mySet.begin();
-               }
-
-               bool more()
-               {
-                       while((myIterator!=mySet.end()))
-                       {
-                               if((*myIterator)->GetID()!=-1)
-                                       return true;
-                               myIterator++;
-                       }
-                       return false;
-               }
-
-               const SMDS_MeshEdge* next()
-               {
-                       const SMDS_MeshEdge* current=*myIterator;
-                       myIterator++;
-                       return current; 
-               }       
-       };
-       return new MyIterator(myEdges);
+  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
 }
 
-///////////////////////////////////////////////////////////////////////////////
-///Return an iterator on faces of the current mesh. Once used this iterator
-///must be free by the caller
-///////////////////////////////////////////////////////////////////////////////
-SMDS_Iterator<const SMDS_MeshFace *> * SMDS_Mesh::facesIterator() const
+SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
 {
-       class MyIterator:public SMDS_Iterator<const SMDS_MeshFace*>
-       {
-               const SetOfFaces& mySet;
-               set<SMDS_MeshFace*>::iterator myIterator;
-         public:
-               MyIterator(const SetOfFaces& s):mySet(s)
-               {
-                       myIterator=mySet.begin();
-               }
-
-               bool more()
-               {
-                       while((myIterator!=mySet.end()))
-                       {
-                               if((*myIterator)->GetID()!=-1)
-                                       return true;
-                               myIterator++;
-                       }
-                       return false;
-               }
-
-               const SMDS_MeshFace* next()
-               {
-                       const SMDS_MeshFace* current=*myIterator;
-                       myIterator++;
-                       return current; 
-               }       
-       };
-       return new MyIterator(myFaces);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Return an iterator on volumes of the current mesh. Once used this iterator
-///must be free by the caller
-///////////////////////////////////////////////////////////////////////////////
-SMDS_Iterator<const SMDS_MeshVolume *> * SMDS_Mesh::volumesIterator() const
-{
-       class MyIterator:public SMDS_Iterator<const SMDS_MeshVolume*>
-       {
-               const SetOfVolumes& mySet;
-               SetOfVolumes::iterator myIterator;
-         public:
-               MyIterator(const SetOfVolumes& s):mySet(s)
-               {
-                       myIterator=mySet.begin();
-               }
-
-               bool more()
-               {
-                       return myIterator!=mySet.end();
-               }
-
-               const SMDS_MeshVolume* next()
-               {
-                       const SMDS_MeshVolume* current=*myIterator;
-                       myIterator++;
-                       return current; 
-               }       
-       };
-       return new MyIterator(myVolumes);
+  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Do intersection of sets (more than 2)
 ///////////////////////////////////////////////////////////////////////////////
-set<const SMDS_MeshElement*> * intersectionOfSets(
-       set<const SMDS_MeshElement*> vs[], int numberOfSets)
+static std::set<const SMDS_MeshElement*> *
+intersectionOfSets( std::set<const SMDS_MeshElement*> vs[], int numberOfSets )
 {
-       set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
-       set<const SMDS_MeshElement*>* rsetB;
+  std::set<const SMDS_MeshElement*>* rsetA = new std::set<const SMDS_MeshElement*>(vs[0]);
+  std::set<const SMDS_MeshElement*>* rsetB;
 
-       for(int i=0; i<numberOfSets-1; i++)
-       {
-               rsetB=new set<const SMDS_MeshElement*>();
-               set_intersection(
-                       rsetA->begin(), rsetA->end(),
-                       vs[i+1].begin(), vs[i+1].end(),
-                       inserter(*rsetB, rsetB->begin()));
-               delete rsetA;
-               rsetA=rsetB;
-       }
-       return rsetA;
+  for(int i=0; i<numberOfSets-1; i++)
+  {
+    rsetB = new std::set<const SMDS_MeshElement*>();
+    set_intersection(rsetA->begin(), rsetA->end(),
+                     vs[i+1].begin(), vs[i+1].end(),
+                     inserter(*rsetB, rsetB->begin()));
+    delete rsetA;
+    rsetA=rsetB;
+  }
+  return rsetA;
 }
-
 ///////////////////////////////////////////////////////////////////////////////
-/// Return the list of finit elements owning the given element
+/// Return the list of finite elements owning the given element: elements
+/// containing all the nodes of the given element, for instance faces and
+/// volumes containing a given edge.
 ///////////////////////////////////////////////////////////////////////////////
-set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
+static std::set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
 {
-       int numberOfSets=element->NbNodes();
-       set<const SMDS_MeshElement*> initSet[numberOfSets];
-
-       SMDS_Iterator<const SMDS_MeshElement*> * itNodes=element->nodesIterator();
+  int numberOfSets=element->NbNodes();
+  std::set<const SMDS_MeshElement*> *initSet = new std::set<const SMDS_MeshElement*>[numberOfSets];
 
-       int i=0;
-       while(itNodes->more())
-       {
-               const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
-               SMDS_Iterator<const SMDS_MeshElement*> * itFe = n->GetInverseElementIterator();
+  SMDS_NodeIteratorPtr itNodes = element->nodeIterator();
 
-               //initSet[i]=set<const SMDS_MeshElement*>();
-               while(itFe->more()) initSet[i].insert(itFe->next());
-
-               i++;
-               delete itFe;
-       }
-       delete itNodes;
-       
-       return intersectionOfSets(initSet, numberOfSets);
+  int i = 0;
+  while ( itNodes->more() )
+  {
+    const SMDS_MeshNode *   n = itNodes->next();
+    for ( SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); itFe->more(); )
+      initSet[i].insert( itFe->next() );
+    i++;
+  }
+  std::set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
+  delete [] initSet;
+  return retSet;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return the list of nodes used only by the given elements
+/// Return the std::list of nodes used only by the given elements
 ///////////////////////////////////////////////////////////////////////////////
-set<const SMDS_MeshElement*> * getExclusiveNodes(
-       set<const SMDS_MeshElement*>& elements)
+static
+std::set<const SMDS_MeshElement*> *getExclusiveNodes(std::set<const SMDS_MeshElement*>& elements)
 {
-       set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
-       set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
+  std::set<const SMDS_MeshElement*> *           toReturn = new std::set<const SMDS_MeshElement*>();
+  std::set<const SMDS_MeshElement*>::iterator itElements = elements.begin();
+
+  while( itElements != elements.end() )
+  {
+    SMDS_NodeIteratorPtr itNodes = (*itElements)->nodeIterator();
+    itElements++;
 
-       while(itElements!=elements.end())
-       {
-               SMDS_Iterator<const SMDS_MeshElement*> * itNodes=
-                       (*itElements)->nodesIterator();
-               itElements++;
-       
-               while(itNodes->more())
-               {
-                       const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
-                       SMDS_Iterator<const SMDS_MeshElement*> * itFe = n->GetInverseElementIterator();
-                       set<const SMDS_MeshElement*> s;
-                       while(itFe->more()) s.insert(itFe->next());
-                       delete itFe;
-                       if(s==elements) toReturn->insert(n);
-               }
-               delete itNodes;
-       }
-       return toReturn;        
+    while( itNodes->more() )
+    {
+      const SMDS_MeshNode *   n = itNodes->next();
+      SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+      std::set<const SMDS_MeshElement*> s;
+      while ( itFe->more() )
+        s.insert( itFe->next() );
+      if ( s == elements ) toReturn->insert(n);
+    }
+  }
+  return toReturn;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Find the children of an element that are made of given nodes 
+///Find the children of an element that are made of given nodes
 ///@param setOfChildren The set in which matching children will be inserted
 ///@param element The element were to search matching children
 ///@param nodes The nodes that the children must have to be selected
 ///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&     setOfChildren, 
-       const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
-{
-       
-       switch(element->GetType())
-       {
-       case SMDSAbs_Node:
-               MESSAGE("Internal Error: This should not append");
-               break;
-       case SMDSAbs_Edge:
-       {
-               SMDS_Iterator<const SMDS_MeshElement*> * itn=element->nodesIterator();
-               while(itn->more())
-               {
-                       const SMDS_MeshElement * e=itn->next();
-                       if(nodes.find(e)!=nodes.end()) setOfChildren.insert(element);
-               }
-               delete itn;
-       } break;        
-       case SMDSAbs_Face:
-       {
-               SMDS_Iterator<const SMDS_MeshElement*> * itn=element->nodesIterator();
-               while(itn->more())
-               {
-                       const SMDS_MeshElement * e=itn->next();
-                       if(nodes.find(e)!=nodes.end()) setOfChildren.insert(element);
-               }
-               delete itn;
-               if(hasConstructionEdges())
-               {
-                       SMDS_Iterator<const SMDS_MeshElement*>* ite=element->edgesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                       delete ite;
-               }
-       } break;        
-       case SMDSAbs_Volume:
-       {
-               if(hasConstructionFaces())
-               {
-                       SMDS_Iterator<const SMDS_MeshElement*> * ite=element->facesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                       delete ite;
-               }
-               else if(hasConstructionEdges())
-               {
-                       SMDS_Iterator<const SMDS_MeshElement*> * ite=element->edgesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                       delete ite;
-               }
-       }
-       }
+void SMDS_Mesh::addChildrenWithNodes(std::set<const SMDS_MeshElement*>& setOfChildren,
+                                     const SMDS_MeshElement *           element,
+                                     std::set<const SMDS_MeshElement*>& nodes)
+{
+  switch(element->GetType())
+  {
+  case SMDSAbs_Node:
+    throw SALOME_Exception("Internal Error: This should not happen");
+    break;
+  case SMDSAbs_0DElement:
+  case SMDSAbs_Ball:
+  {
+  }
+  break;
+  case SMDSAbs_Edge:
+  {
+    SMDS_ElemIteratorPtr itn=element->nodesIterator();
+    while(itn->more())
+    {
+      const SMDS_MeshElement * e=itn->next();
+      if(nodes.find(e)!=nodes.end())
+      {
+        setOfChildren.insert(element);
+        break;
+      }
+    }
+  } break;
+  case SMDSAbs_Face:
+  {
+    SMDS_ElemIteratorPtr itn=element->nodesIterator();
+    while(itn->more())
+    {
+      const SMDS_MeshElement * e=itn->next();
+      if(nodes.find(e)!=nodes.end())
+      {
+        setOfChildren.insert(element);
+        break;
+      }
+    }
+  } break;
+  case SMDSAbs_Volume:
+  case SMDSAbs_NbElementTypes:
+  case SMDSAbs_All: break;
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1518,56 +1750,1243 @@ void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&    setOfChildren
 ///@param removenodes if true remaining nodes will be removed
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
-       const bool removenodes)
-{
-       set<const SMDS_MeshElement*> * s1=getFinitElements(elem);
-       
-       set<const SMDS_MeshElement*> * s2=getExclusiveNodes(*s1);
-       set<const SMDS_MeshElement*> s3;
-       set<const SMDS_MeshElement*>::iterator it=s1->begin();
-       while(it!=s1->end())
-       {
-               addChildrenWithNodes(s3, *it ,*s2);
-               s3.insert(*it);
-               it++;
-       }
-       if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);      
-       it=s3.begin();
-       while(it!=s3.end())
-       {
-               switch((*it)->GetType())
-               {
-               case SMDSAbs_Node:
-                       MESSAGE("Internal Error: This should not happen");
-                       break;
-               case SMDSAbs_Edge:
-                       myEdges.erase(static_cast<SMDS_MeshEdge*>(
-                               const_cast<SMDS_MeshElement*>(*it)));   
-                       break;
-               case SMDSAbs_Face:
-                       myFaces.erase(static_cast<SMDS_MeshFace*>(
-                               const_cast<SMDS_MeshElement*>(*it)));
-                       break;
-               case SMDSAbs_Volume:
-                       myVolumes.erase(static_cast<SMDS_MeshVolume*>(
-                               const_cast<SMDS_MeshElement*>(*it)));   
-                       break;
-               }
-               delete (*it);
-               it++;
-       }       
-       if(removenodes)
-       {
-               it=s2->begin();
-               while(it!=s2->end())
-               {
-                       myNodes.erase(static_cast<SMDS_MeshNode*>(
-                               const_cast<SMDS_MeshElement*>(*it)));
-                       delete *it;
-                       it++;
-               }
-       }
-               
-       delete s2;
-       delete s1;
+                              const bool               removenodes)
+{
+  std::vector<const SMDS_MeshElement *> removedElems;
+  std::vector<const SMDS_MeshElement *> removedNodes;
+  RemoveElement( elem, removedElems, removedNodes, removenodes );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///@param removedElems to be filled with all removed elements
+///@param removedNodes to be filled with all removed nodes
+///@param removenodes if true remaining nodes will be removed
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
+                              std::vector<const SMDS_MeshElement *>& removedElems,
+                              std::vector<const SMDS_MeshElement *>& removedNodes,
+                              bool                                   removenodes)
+{
+  // get finite elements built on elem
+  std::set<const SMDS_MeshElement*> * s1;
+  if (    (elem->GetType() == SMDSAbs_0DElement)
+          ||  (elem->GetType() == SMDSAbs_Ball)
+          ||  (elem->GetType() == SMDSAbs_Edge)
+          ||  (elem->GetType() == SMDSAbs_Face)
+          ||  (elem->GetType() == SMDSAbs_Volume) )
+  {
+    s1 = new std::set<const SMDS_MeshElement*> ();
+    s1->insert(elem);
+  }
+  else
+    s1 = getFinitElements(elem);
+
+  // get exclusive nodes (which would become free afterwards)
+  std::set<const SMDS_MeshElement*> * s2;
+  if (elem->GetType() == SMDSAbs_Node) // a node is removed
+  {
+    // do not remove nodes except elem
+    s2 = new std::set<const SMDS_MeshElement*> ();
+    s2->insert(elem);
+    removenodes = true;
+  }
+  else
+    s2 = getExclusiveNodes(*s1);
+
+  // form the set of finite and construction elements to remove
+  std::set<const SMDS_MeshElement*> s3;
+  std::set<const SMDS_MeshElement*>::iterator it = s1->begin();
+  while (it != s1->end())
+  {
+    addChildrenWithNodes(s3, *it, *s2);
+    s3.insert(*it);
+    it++;
+  }
+  if (elem->GetType() != SMDSAbs_Node)
+    s3.insert(elem);
+
+  // remove finite and construction elements
+  for( it = s3.begin();it != s3.end(); ++it )
+  {
+    // Remove element from <InverseElements> of its nodes
+    SMDS_NodeIteratorPtr itn = (*it)->nodeIterator();
+    while (itn->more())
+    {
+      SMDS_MeshNode * n = const_cast<SMDS_MeshNode *> (itn->next());
+      n->RemoveInverseElement((*it));
+    }
+
+    int vtkid = (*it)->GetVtkID();
+
+    switch ((*it)->GetType()) {
+    case SMDSAbs_Node:
+      throw SALOME_Exception(LOCALIZED("Internal Error: This should not happen"));
+      break;
+    case SMDSAbs_Edge:      myInfo.RemoveEdge(*it);   break;
+    case SMDSAbs_Face:      myInfo.RemoveFace(*it);   break;
+    case SMDSAbs_Volume:    myInfo.RemoveVolume(*it); break;
+    case SMDSAbs_Ball:      myInfo.myNbBalls--;       break;
+    case SMDSAbs_0DElement: myInfo.myNb0DElements--;  break;
+    case SMDSAbs_All: // avoid compilation warning
+    case SMDSAbs_NbElementTypes: break;
+    }
+    removedElems.push_back( *it);
+
+    myCellFactory->Free( static_cast< const SMDS_MeshCell*>( *it ));
+
+    if (vtkid >= 0)
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
+    }
+  }
+
+  // remove exclusive (free) nodes
+  if (removenodes)
+  {
+    for ( it = s2->begin(); it != s2->end(); ++it )
+    {
+      myInfo.myNbNodes--;
+      myNodeFactory->Free( (*it) );
+      removedNodes.push_back((*it));
+    }
+  }
+
+  delete s2;
+  delete s1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
+{
+  const int           vtkId = elem->GetVtkID();
+  SMDSAbs_ElementType aType = elem->GetType();
+  if ( aType == SMDSAbs_Node )
+  {
+    // only free node can be removed by this method
+    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( elem );
+    if ( n->NbInverseElements() == 0 ) { // free node
+      myInfo.myNbNodes--;
+      myNodeFactory->Free( n );
+    }
+    else
+    {
+      throw SALOME_Exception( LOCALIZED( "RemoveFreeElement: not a free node" ));
+    }
+  }
+  else
+  {
+    // Remove element from <InverseElements> of its nodes
+    SMDS_NodeIteratorPtr itn = elem->nodeIterator();
+    while (itn->more()) {
+      SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>(itn->next());
+      n->RemoveInverseElement(elem);
+    }
+
+    // in meshes without descendants elements are always free
+    switch (aType) {
+    case SMDSAbs_0DElement: myInfo.remove(elem);       break;
+    case SMDSAbs_Edge:      myInfo.RemoveEdge(elem);   break;
+    case SMDSAbs_Face:      myInfo.RemoveFace(elem);   break;
+    case SMDSAbs_Volume:    myInfo.RemoveVolume(elem); break;
+    case SMDSAbs_Ball:      myInfo.remove(elem);       break;
+    default: break;
+    }
+    myCellFactory->Free( elem );
+
+    this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
+  }
+}
+
+//=======================================================================
+/*!
+ * Checks if the element is present in mesh.
+ */
+//=======================================================================
+
+bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
+{
+  if ( !elem || elem->IsNull() )
+    return false;
+
+  if ( elem->GetType() == SMDSAbs_Node )
+    return ( elem == myNodeFactory->FindElement( elem->GetID() ));
+
+  return ( elem == myCellFactory->FindElement( elem->GetID() ));
+}
+
+//=======================================================================
+//function : MaxNodeID
+//purpose  :
+//=======================================================================
+
+int SMDS_Mesh::MaxNodeID() const
+{
+  return myNodeFactory->GetMaxID();
+}
+
+//=======================================================================
+//function : MinNodeID
+//purpose  :
+//=======================================================================
+
+int SMDS_Mesh::MinNodeID() const
+{
+  return myNodeFactory->GetMinID();
+}
+
+//=======================================================================
+//function : MaxElementID
+//purpose  :
+//=======================================================================
+
+int SMDS_Mesh::MaxElementID() const
+{
+  return myCellFactory->GetMaxID();
+}
+
+//=======================================================================
+//function : MinElementID
+//purpose  :
+//=======================================================================
+
+int SMDS_Mesh::MinElementID() const
+{
+  return myCellFactory->GetMinID();
+}
+
+//=======================================================================
+//function : Renumber
+//purpose  : Renumber all nodes or elements.
+//=======================================================================
+
+// void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
+// {
+//   if ( deltaID == 0 )
+//     return;
+
+// }
+
+//=======================================================================
+//function : GetElementType
+//purpose  : Return type of element or node with id
+//=======================================================================
+
+SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
+{
+  const SMDS_MeshElement* elem = 0;
+  if( iselem )
+    elem = myCellFactory->FindElement( id );
+  else
+    elem = myNodeFactory->FindElement( id );
+
+  return elem ? elem->GetType() : SMDSAbs_All;
+}
+
+
+
+//********************************************************************
+//********************************************************************
+//********                                                   *********
+//*****       Methods for addition of quadratic elements        ******
+//********                                                   *********
+//********************************************************************
+//********************************************************************
+
+//=======================================================================
+//function : AddEdgeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
+{
+  return SMDS_Mesh::AddEdgeWithID (myNodeFactory->FindNode(n1),
+                                   myNodeFactory->FindNode(n2),
+                                   myNodeFactory->FindNode(n12),
+                                   ID);
+}
+
+//=======================================================================
+//function : AddEdge
+//purpose  :
+//=======================================================================
+SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
+                                  const SMDS_MeshNode* n2,
+                                  const SMDS_MeshNode* n12)
+{
+  return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddEdgeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n12,
+                                        int                   ID)
+{
+  if ( !n1 || !n2 || !n12 ) return 0;
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Edge, /*nbNodes=*/3, n1, n2, n12 );
+    myInfo.myNbQuadEdges++;
+    return static_cast<SMDS_MeshEdge*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n31)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
+                                  myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
+                                        int n12,int n23,int n31, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
+                                   myNodeFactory->FindNode(n2) ,
+                                   myNodeFactory->FindNode(n3) ,
+                                   myNodeFactory->FindNode(n12),
+                                   myNodeFactory->FindNode(n23),
+                                   myNodeFactory->FindNode(n31),
+                                   ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n31,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Triangle, /*nbNodes=*/6, n1, n2, n3, n12, n23, n31 );
+    myInfo.myNbQuadTriangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n31,
+                                  const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
+                                  myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
+                                        int n12,int n23,int n31, int nCenter, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
+                                   myNodeFactory->FindNode(n2) ,
+                                   myNodeFactory->FindNode(n3) ,
+                                   myNodeFactory->FindNode(n12),
+                                   myNodeFactory->FindNode(n23),
+                                   myNodeFactory->FindNode(n31),
+                                   myNodeFactory->FindNode(nCenter),
+                                   ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n31,
+                                        const SMDS_MeshNode * nCenter,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_BiQuad_Triangle, /*nbNodes=*/7, n1, n2, n3, n12, n23, n31, nCenter );
+    myInfo.myNbBiQuadTriangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n34,
+                                  const SMDS_MeshNode * n41)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
+                                  myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
+                                        int n12,int n23,int n34,int n41, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
+                                   myNodeFactory->FindNode(n2) ,
+                                   myNodeFactory->FindNode(n3) ,
+                                   myNodeFactory->FindNode(n4) ,
+                                   myNodeFactory->FindNode(n12),
+                                   myNodeFactory->FindNode(n23),
+                                   myNodeFactory->FindNode(n34),
+                                   myNodeFactory->FindNode(n41),
+                                   ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Quadrangle, /*nbNodes=*/8, n1, n2, n3, n4, n12, n23, n34, n41 );
+    myInfo.myNbQuadQuadrangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n34,
+                                  const SMDS_MeshNode * n41,
+                                  const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
+                                  myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
+                                        int n12,int n23,int n34,int n41, int nCenter, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
+                                   myNodeFactory->FindNode(n2) ,
+                                   myNodeFactory->FindNode(n3) ,
+                                   myNodeFactory->FindNode(n4) ,
+                                   myNodeFactory->FindNode(n12),
+                                   myNodeFactory->FindNode(n23),
+                                   myNodeFactory->FindNode(n34),
+                                   myNodeFactory->FindNode(n41),
+                                   myNodeFactory->FindNode(nCenter),
+                                   ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
+                                        const SMDS_MeshNode * nCenter,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_BiQuad_Quadrangle,
+                /*nbNodes=*/9, n1, n2, n3, n4, n12, n23, n34, n41, nCenter );
+    myInfo.myNbBiQuadQuadrangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n31,
+                                      const SMDS_MeshNode * n14,
+                                      const SMDS_MeshNode * n24,
+                                      const SMDS_MeshNode * n34)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
+                                    n31, n14, n24, n34, myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n12,int n23,int n31,
+                                            int n14,int n24,int n34, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
+                                     myNodeFactory->FindNode(n2) ,
+                                     myNodeFactory->FindNode(n3) ,
+                                     myNodeFactory->FindNode(n4) ,
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n31),
+                                     myNodeFactory->FindNode(n14),
+                                     myNodeFactory->FindNode(n24),
+                                     myNodeFactory->FindNode(n34),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order tetrahedron of 10 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n31,
+                                            const SMDS_MeshNode * n14,
+                                            const SMDS_MeshNode * n24,
+                                            const SMDS_MeshNode * n34,
+                                            int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Tetra,
+                /*nbNodes=*/10, n1, n2, n3, n4, n12, n23, n31, n14, n24, n34 );
+    myInfo.myNbQuadTetras++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n25,
+                                      const SMDS_MeshNode * n35,
+                                      const SMDS_MeshNode * n45)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
+                                    n15, n25, n35, n45, myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
+                                            int n12,int n23,int n34,int n41,
+                                            int n15,int n25,int n35,int n45, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
+                                     myNodeFactory->FindNode(n2) ,
+                                     myNodeFactory->FindNode(n3) ,
+                                     myNodeFactory->FindNode(n4) ,
+                                     myNodeFactory->FindNode(n5) ,
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n34),
+                                     myNodeFactory->FindNode(n41),
+                                     myNodeFactory->FindNode(n15),
+                                     myNodeFactory->FindNode(n25),
+                                     myNodeFactory->FindNode(n35),
+                                     myNodeFactory->FindNode(n45),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order pyramid of 13 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n25,
+                                            const SMDS_MeshNode * n35,
+                                            const SMDS_MeshNode * n45,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
+      !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Pyramid,
+                /*nbNodes=*/13, n1, n2, n3, n4, n5, n12, n23, n34, n41, n15, n25, n35, n45);
+    myInfo.myNbQuadPyramids++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::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 * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n31,
+                                      const SMDS_MeshNode * n45,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n64,
+                                      const SMDS_MeshNode * n14,
+                                      const SMDS_MeshNode * n25,
+                                      const SMDS_MeshNode * n36)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
+                                    n45, n56, n64, n14, n25, n36, myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
+                                            int n4, int n5, int n6,
+                                            int n12,int n23,int n31,
+                                            int n45,int n56,int n64,
+                                            int n14,int n25,int n36, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
+                                     myNodeFactory->FindNode(n2) ,
+                                     myNodeFactory->FindNode(n3) ,
+                                     myNodeFactory->FindNode(n4) ,
+                                     myNodeFactory->FindNode(n5) ,
+                                     myNodeFactory->FindNode(n6) ,
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n31),
+                                     myNodeFactory->FindNode(n45),
+                                     myNodeFactory->FindNode(n56),
+                                     myNodeFactory->FindNode(n64),
+                                     myNodeFactory->FindNode(n14),
+                                     myNodeFactory->FindNode(n25),
+                                     myNodeFactory->FindNode(n36),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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 * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n31,
+                                            const SMDS_MeshNode * n45,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n64,
+                                            const SMDS_MeshNode * n14,
+                                            const SMDS_MeshNode * n25,
+                                            const SMDS_MeshNode * n36,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
+      !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Penta, /*nbNodes=*/15,
+                n1, n2, n3, n4, n5, n6, n12, n23, n31, n45, n56, n64, n14, n25, n36 );
+    myInfo.myNbQuadPrisms++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : AddVolume
+//purpose  : 2d order Pentahedron (prism) with 18 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::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 * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n31,
+                                      const SMDS_MeshNode * n45,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n64,
+                                      const SMDS_MeshNode * n14,
+                                      const SMDS_MeshNode * n25,
+                                      const SMDS_MeshNode * n36,
+                                      const SMDS_MeshNode * n1245,
+                                      const SMDS_MeshNode * n2356,
+                                      const SMDS_MeshNode * n1346)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
+                                    n45, n56, n64, n14, n25, n36, n1245, n2356, n1346,
+                                    myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron (prism) with 18 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
+                                            int n4, int n5, int n6,
+                                            int n12,int n23,int n31,
+                                            int n45,int n56,int n64,
+                                            int n14,int n25,int n36,
+                                            int n1245, int n2356, int n1346, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
+                                     myNodeFactory->FindNode(n2) ,
+                                     myNodeFactory->FindNode(n3) ,
+                                     myNodeFactory->FindNode(n4) ,
+                                     myNodeFactory->FindNode(n5) ,
+                                     myNodeFactory->FindNode(n6) ,
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n31),
+                                     myNodeFactory->FindNode(n45),
+                                     myNodeFactory->FindNode(n56),
+                                     myNodeFactory->FindNode(n64),
+                                     myNodeFactory->FindNode(n14),
+                                     myNodeFactory->FindNode(n25),
+                                     myNodeFactory->FindNode(n36),
+                                     myNodeFactory->FindNode(n1245),
+                                     myNodeFactory->FindNode(n2356),
+                                     myNodeFactory->FindNode(n1346),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron (prism) with 18 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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 * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n31,
+                                            const SMDS_MeshNode * n45,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n64,
+                                            const SMDS_MeshNode * n14,
+                                            const SMDS_MeshNode * n25,
+                                            const SMDS_MeshNode * n36,
+                                            const SMDS_MeshNode * n1245,
+                                            const SMDS_MeshNode * n2356,
+                                            const SMDS_MeshNode * n1346,
+                                            int ID)
+{
+  //MESSAGE("AddVolumeWithID penta18 "<< ID);
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
+      !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36 || !n1245 || !n2356 || !n1346)
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_BiQuad_Penta, /*nbNodes=*/18, n1, n2, n3, n4, n5, n6,
+                n12, n23, n31, n45, n56, n64, n14, n25, n36, n1245, n2356, n1346 );
+    myInfo.myNbBiQuadPrisms++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::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,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n67,
+                                      const SMDS_MeshNode * n78,
+                                      const SMDS_MeshNode * n85,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n26,
+                                      const SMDS_MeshNode * n37,
+                                      const SMDS_MeshNode * n48)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
+                                    n56, n67, n78, n85, n15, n26, n37, n48,
+                                    myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n5, int n6, int n7, int n8,
+                                            int n12,int n23,int n34,int n41,
+                                            int n56,int n67,int n78,int n85,
+                                            int n15,int n26,int n37,int n48, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
+                                     myNodeFactory->FindNode(n2),
+                                     myNodeFactory->FindNode(n3),
+                                     myNodeFactory->FindNode(n4),
+                                     myNodeFactory->FindNode(n5),
+                                     myNodeFactory->FindNode(n6),
+                                     myNodeFactory->FindNode(n7),
+                                     myNodeFactory->FindNode(n8),
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n34),
+                                     myNodeFactory->FindNode(n41),
+                                     myNodeFactory->FindNode(n56),
+                                     myNodeFactory->FindNode(n67),
+                                     myNodeFactory->FindNode(n78),
+                                     myNodeFactory->FindNode(n85),
+                                     myNodeFactory->FindNode(n15),
+                                     myNodeFactory->FindNode(n26),
+                                     myNodeFactory->FindNode(n37),
+                                     myNodeFactory->FindNode(n48),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Hexahedrons with 20 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n67,
+                                            const SMDS_MeshNode * n78,
+                                            const SMDS_MeshNode * n85,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n26,
+                                            const SMDS_MeshNode * n37,
+                                            const SMDS_MeshNode * n48,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Quad_Hexa, /*nbNodes=*/20, n1, n2, n3, n4, n5, n6, n7, n8,
+                n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48 );
+    myInfo.myNbQuadHexas++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::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,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n67,
+                                      const SMDS_MeshNode * n78,
+                                      const SMDS_MeshNode * n85,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n26,
+                                      const SMDS_MeshNode * n37,
+                                      const SMDS_MeshNode * n48,
+                                      const SMDS_MeshNode * n1234,
+                                      const SMDS_MeshNode * n1256,
+                                      const SMDS_MeshNode * n2367,
+                                      const SMDS_MeshNode * n3478,
+                                      const SMDS_MeshNode * n1458,
+                                      const SMDS_MeshNode * n5678,
+                                      const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
+                                    n56, n67, n78, n85, n15, n26, n37, n48,
+                                    n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
+                                    myCellFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n5, int n6, int n7, int n8,
+                                            int n12,int n23,int n34,int n41,
+                                            int n56,int n67,int n78,int n85,
+                                            int n15,int n26,int n37,int n48,
+                                            int n1234,int n1256,int n2367,int n3478,
+                                            int n1458,int n5678,int nCenter, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
+                                     myNodeFactory->FindNode(n2),
+                                     myNodeFactory->FindNode(n3),
+                                     myNodeFactory->FindNode(n4),
+                                     myNodeFactory->FindNode(n5),
+                                     myNodeFactory->FindNode(n6),
+                                     myNodeFactory->FindNode(n7),
+                                     myNodeFactory->FindNode(n8),
+                                     myNodeFactory->FindNode(n12),
+                                     myNodeFactory->FindNode(n23),
+                                     myNodeFactory->FindNode(n34),
+                                     myNodeFactory->FindNode(n41),
+                                     myNodeFactory->FindNode(n56),
+                                     myNodeFactory->FindNode(n67),
+                                     myNodeFactory->FindNode(n78),
+                                     myNodeFactory->FindNode(n85),
+                                     myNodeFactory->FindNode(n15),
+                                     myNodeFactory->FindNode(n26),
+                                     myNodeFactory->FindNode(n37),
+                                     myNodeFactory->FindNode(n48),
+                                     myNodeFactory->FindNode(n1234),
+                                     myNodeFactory->FindNode(n1256),
+                                     myNodeFactory->FindNode(n2367),
+                                     myNodeFactory->FindNode(n3478),
+                                     myNodeFactory->FindNode(n1458),
+                                     myNodeFactory->FindNode(n5678),
+                                     myNodeFactory->FindNode(nCenter),
+                                     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Hexahedrons with 27 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(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_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n67,
+                                            const SMDS_MeshNode * n78,
+                                            const SMDS_MeshNode * n85,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n26,
+                                            const SMDS_MeshNode * n37,
+                                            const SMDS_MeshNode * n48,
+                                            const SMDS_MeshNode * n1234,
+                                            const SMDS_MeshNode * n1256,
+                                            const SMDS_MeshNode * n2367,
+                                            const SMDS_MeshNode * n3478,
+                                            const SMDS_MeshNode * n1458,
+                                            const SMDS_MeshNode * n5678,
+                                            const SMDS_MeshNode * nCenter,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
+      !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
+    return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_TriQuad_Hexa, /*nbNodes=*/27, n1, n2, n3, n4, n5, n6, n7, n8,
+                n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48,
+                n1234, n1256, n2367, n3478, n1458, n5678, nCenter);
+    myInfo.myNbTriQuadHexas++;
+    return static_cast<SMDS_MeshVolume*>( cell );
+  }
+  return 0;
+}
+
+void SMDS_Mesh::dumpGrid(std::string ficdump)
+{
+  //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
+  //  aWriter->SetFileName(ficdump.c_str());
+  //  aWriter->SetInput(myGrid);
+  //  if(myGrid->GetNumberOfCells())
+  //  {
+  //    aWriter->Write();
+  //  }
+  //  aWriter->Delete();
+  ficdump = ficdump + "_connectivity";
+  std::ofstream ficcon(ficdump.c_str(), ios::out);
+  int nbPoints = myGrid->GetNumberOfPoints();
+  ficcon << "-------------------------------- points " <<  nbPoints << endl;
+  for (int i=0; i<nbPoints; i++)
+  {
+    ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
+  }
+  int nbCells = myGrid->GetNumberOfCells();
+  ficcon << "-------------------------------- cells " <<  nbCells << endl;
+  for (int i=0; i<nbCells; i++)
+  {
+    ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
+    int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
+    vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
+    for (int j=0; j<nbptcell; j++)
+    {
+      ficcon << " " <<  listid->GetId(j);
+    }
+    ficcon << endl;
+  }
+  ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
+  vtkCellLinks *links = myGrid->GetLinks();
+  for (int i=0; i<nbPoints; i++)
+  {
+    int ncells = links->GetNcells(i);
+    vtkIdType *cells = links->GetCells(i);
+    ficcon << i << " - " << ncells << " -";
+    for (int j=0; j<ncells; j++)
+    {
+      ficcon << " " << cells[j];
+    }
+    ficcon << endl;
+  }
+  ficcon.close();
+
+}
+
+void SMDS_Mesh::CompactMesh()
+{
+  this->myCompactTime = this->myModifTime;
+
+  bool idsChange = ( myNodeFactory->CompactChangePointers() ||
+                     myCellFactory->CompactChangePointers() );
+  if ( idsChange )
+  {
+    std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
+    for ( ; holder != myElemHolders.end(); ++holder )
+      (*holder)->beforeCompacting();
+  }
+  int oldCellSize = myCellFactory->GetMaxID();
+
+  // remove "holes" in SMDS numeration
+  std::vector<int> idNodesOldToNew, idCellsNewToOld, idCellsOldToNew;
+  myNodeFactory->Compact( idNodesOldToNew );
+  myCellFactory->Compact( idCellsNewToOld );
+
+  // make VTK IDs correspond to SMDS IDs
+  int newNodeSize = myNodeFactory->NbUsedElements();
+  int newCellSize = myCellFactory->NbUsedElements();
+  myGrid->compactGrid( idNodesOldToNew, newNodeSize, idCellsNewToOld, newCellSize );
+
+  if ( idsChange && !myElemHolders.empty() )
+  {
+    // idCellsNewToOld -> idCellsOldToNew
+    idCellsOldToNew.resize( oldCellSize, oldCellSize );
+    for ( size_t iNew = 0; iNew < idCellsNewToOld.size(); ++iNew )
+    {
+      if ( idCellsNewToOld[ iNew ] >= (int) idCellsOldToNew.size() )
+        idCellsOldToNew.resize( ( 1 + idCellsNewToOld[ iNew ]) * 1.5, oldCellSize );
+      idCellsOldToNew[ idCellsNewToOld[ iNew ]] = iNew;
+    }
+  }
+
+  std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
+  for ( ; holder != myElemHolders.end(); ++holder )
+    if ( idsChange )
+      (*holder)->restoreElements( idNodesOldToNew, idCellsOldToNew );
+    else
+      (*holder)->compact();
+
+  return;
+}
+
+int SMDS_Mesh::FromVtkToSmds( int vtkid ) const
+{
+  return myCellFactory->FromVtkToSmds( vtkid );
+}
+
+double SMDS_Mesh::getMaxDim()
+{
+  double dmax = 1.e-3;
+  if ((xmax - xmin) > dmax) dmax = xmax -xmin;
+  if ((ymax - ymin) > dmax) dmax = ymax -ymin;
+  if ((zmax - zmin) > dmax) dmax = zmax -zmin;
+  return dmax;
+}
+
+//! modification that needs compact structure and redraw
+void SMDS_Mesh::Modified()
+{
+  if (this->myModified)
+  {
+    this->myModifTime++;
+    myModified = false;
+  }
+}
+
+//! get last modification timeStamp
+vtkMTimeType SMDS_Mesh::GetMTime() const
+{
+  return this->myModifTime;
+}
+
+bool SMDS_Mesh::IsCompacted()
+{
+  return ( this->myCompactTime == this->myModifTime );
+}
+
+void SMDS_Mesh::setNbShapes( size_t nbShapes )
+{
+  myNodeFactory->SetNbShapes( nbShapes );
 }