Salome HOME
023544: SMESH's performance issues (note 22293)
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 58641e56bc44f284cc5c37b5f90555bc61f9a7ab..43a48eb37f23095e4f666dd64df2ed7c84a93487 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #pragma warning(disable:4786)
 #endif
 
-#include "SMDS_FaceOfEdges.hxx"
-#include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_Mesh.hxx"
-#include "SMDS_PolygonalFaceOfNodes.hxx"
-#include "SMDS_PolyhedralVolumeOfNodes.hxx"
-#include "SMDS_QuadraticEdge.hxx"
-#include "SMDS_QuadraticFaceOfNodes.hxx"
-#include "SMDS_QuadraticVolumeOfNodes.hxx"
+
+#include "SMDS_ElementFactory.hxx"
+#include "SMDS_ElementHolder.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMDS_SpacePosition.hxx"
 #include "SMDS_UnstructuredGrid.hxx"
-#include "SMDS_VolumeOfFaces.hxx"
-#include "SMDS_VolumeOfNodes.hxx"
 
-#include "utilities.h"
+#include <utilities.h>
 
 #include <vtkUnstructuredGrid.h>
-#include <vtkUnstructuredGridWriter.h>
-#include <vtkUnsignedCharArray.h>
+//#include <vtkUnstructuredGridWriter.h>
 #include <vtkCell.h>
+#include <vtkUnsignedCharArray.h>
 #include <vtkCellLinks.h>
 #include <vtkIdList.h>
 
 #include <algorithm>
-#include <map>
 #include <iostream>
 #include <fstream>
-#include <iterator>
-using namespace std;
 
-#ifndef WIN32
+#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
 
-vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
-int SMDS_Mesh::chunkSize = 1024;
+#define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
 
+int SMDS_Mesh::chunkSize = 1024;
 
 //================================================================================
 /*!
@@ -77,7 +70,8 @@ int SMDS_Mesh::chunkSize = 1024;
 
 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
 {
-#ifndef WIN32
+  return -1;
+#if !defined WIN32 && !defined __APPLE__
   struct sysinfo si;
   int err = sysinfo( &si );
   if ( err )
@@ -87,13 +81,16 @@ int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
 
   static int limit = -1;
   if ( limit < 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 ( 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;
@@ -106,7 +103,6 @@ int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
   int freeMb =
     ( si.freeram  * si.mem_unit ) / Mbyte +
     ( si.freeswap * si.mem_unit ) / Mbyte;
-  //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
 
   if ( freeMb > limit )
     return freeMb - limit;
@@ -124,31 +120,13 @@ int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
 ///////////////////////////////////////////////////////////////////////////////
 /// Create a new mesh object
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Mesh::SMDS_Mesh()
-  :myParent(NULL),
-   myNodeIDFactory(new SMDS_MeshNodeIDFactory()),
-   myElementIDFactory(new SMDS_MeshElementIDFactory()),
-   myHasConstructionEdges(false), myHasConstructionFaces(false),
-   myHasInverseElements(true),
-   myNodeMin(0), myNodeMax(0),
-   myNodePool(0), myEdgePool(0), myFacePool(0), myVolumePool(0),myBallPool(0),
-   myModified(false), myModifTime(0), myCompactTime(0),
-   xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
-{
-  myMeshId = _meshList.size();         // --- index of the mesh to push back in the vector
-  myNodeIDFactory->SetMesh(this);
-  myElementIDFactory->SetMesh(this);
-  _meshList.push_back(this);
-  myNodePool = new ObjectPool<SMDS_MeshNode>(SMDS_Mesh::chunkSize);
-  myEdgePool = new ObjectPool<SMDS_VtkEdge>(SMDS_Mesh::chunkSize);
-  myFacePool = new ObjectPool<SMDS_VtkFace>(SMDS_Mesh::chunkSize);
-  myVolumePool = new ObjectPool<SMDS_VtkVolume>(SMDS_Mesh::chunkSize);
-  myBallPool = new ObjectPool<SMDS_BallElement>(SMDS_Mesh::chunkSize);
-
-  myNodes.clear();
-  myCells.clear();
-  //myCellIdSmdsToVtk.clear();
-  myCellIdVtkToSmds.clear();
+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();
@@ -157,11 +135,13 @@ SMDS_Mesh::SMDS_Mesh()
   // 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 /*SMDS_Mesh::chunkSize*/);
+  points->SetNumberOfPoints( 0 );
   myGrid->SetPoints( points );
   points->Delete();
-  myGrid->BuildLinks();
   this->Modified();
+
+  // initialize static maps in SMDS_MeshCell, to be thread-safe
+  SMDS_MeshCell::InitStaticMembers();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -169,16 +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),
-         myNodePool(parent->myNodePool),
-         myEdgePool(parent->myEdgePool),
-         myFacePool(parent->myFacePool),
-         myVolumePool(parent->myVolumePool),
-         myBallPool(parent->myBallPool)
+SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
+  myNodeFactory( new SMDS_NodeFactory( this )),
+  myCellFactory( new SMDS_ElementFactory( this )),
+  myParent(parent)
 {
 }
 
@@ -188,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;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -201,7 +175,7 @@ SMDS_Mesh *SMDS_Mesh::AddSubMesh()
 
 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
 {
-  return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
+  return SMDS_Mesh::AddNodeWithID( x,y,z, myNodeFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -209,33 +183,18 @@ 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
-  const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
-  if(!node){
-    if (ID < 1)
-      {
-        MESSAGE("=============>  Bad Node Id: " << ID);
-        ID = myNodeIDFactory->GetFreeID();
-      }
-    myNodeIDFactory->adjustMaxId(ID);
-    SMDS_MeshNode * node = myNodePool->getNew();
-    node->init(ID, myMeshId, 0, x, y, z);
-
-    if (ID >= myNodes.size())
-    {
-        myNodes.resize(ID+SMDS_Mesh::chunkSize, 0);
-//         MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
-    }
-    myNodes[ID] = node;
-    myNodeIDFactory->BindID(ID,node);
+  SMDS_MeshNode *node = myNodeFactory->NewNode( ID );
+  if ( node )
+  {
+    node->init( x, y, z );
     myInfo.myNbNodes++;
     myModified = true;
     this->adjustBoundingBox(x, y, z);
-    return node;
-  }else
-    return NULL;
+  }
+  return node;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -244,7 +203,7 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
 {
-  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  const SMDS_MeshNode * node = myNodeFactory->FindNode(idnode);
   if (!node) return NULL;
   return SMDS_Mesh::Add0DElementWithID(node, ID);
 }
@@ -255,7 +214,7 @@ SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
 {
-  return SMDS_Mesh::Add0DElementWithID(node, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::Add0DElementWithID( node, myCellFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -270,30 +229,26 @@ SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int I
   if (!n) return 0;
 
   if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
-  //MESSAGE("Add0DElementWithID" << ID)
-  SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
-  if (myElementIDFactory->BindID(ID, el0d)) {
-    //SMDS_MeshNode *node = const_cast<SMDS_MeshNode*>(n);
-    //node->AddInverseElement(el0d);// --- fait avec BindID
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = el0d;
+
+  if ( SMDS_MeshCell * cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_0D, /*nbNodes=*/1, n );
     myInfo.myNb0DElements++;
-    return el0d;
+    return static_cast< SMDS_Mesh0DElement*> ( cell );
   }
 
-  delete el0d;
-  return NULL;
+  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)
+SMDS_BallElement* SMDS_Mesh::AddBallWithID( int idnode, double diameter, int ID )
 {
-  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  const SMDS_MeshNode * node = myNodeFactory->FindNode( idnode );
   if (!node) return NULL;
-  return SMDS_Mesh::AddBallWithID(node, diameter, ID);
+  return SMDS_Mesh::AddBallWithID( node, diameter, ID );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -302,7 +257,7 @@ SMDS_BallElement* SMDS_Mesh::AddBallWithID(int idnode, double diameter, int ID)
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
 {
-  return SMDS_Mesh::AddBallWithID(node, diameter, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddBallWithID(node, diameter, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -319,17 +274,12 @@ SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diame
 
   if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
 
-  SMDS_BallElement *ball = myBallPool->getNew();
-  ball->init(n->getVtkId(), diameter, this);
-  if (!this->registerElement(ID,ball))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
-      myBallPool->destroy(ball);
-      return 0;
-    }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = ball;
-  myInfo.myNbBalls++;
+  SMDS_BallElement* ball = static_cast< SMDS_BallElement*>( myCellFactory->NewElement( ID ));
+  if ( ball )
+  {
+    ball->init( n, diameter );
+    myInfo.myNbBalls++;
+  }
   return ball;
 }
 
@@ -340,8 +290,8 @@ SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diame
 
 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);
+  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);
 }
@@ -354,7 +304,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
                                   const SMDS_MeshNode * node2)
 {
-  return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddEdgeWithID(node1, node2, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -368,36 +318,17 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
 
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n2,
-                                        int ID)
+                                        int                   ID)
 {
   if ( !n1 || !n2 ) return 0;
-  SMDS_MeshEdge * edge = 0;
-
-  // --- retreive nodes ID
-  vector<vtkIdType> nodeIds;
-  nodeIds.clear();
-  nodeIds.push_back(n1->getVtkId());
-  nodeIds.push_back(n2->getVtkId());
-
-  SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
-  edgevtk->init(nodeIds, this);
-  if (!this->registerElement(ID,edgevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
-      myEdgePool->destroy(edgevtk);
-      return 0;
-    }
-  edge = edgevtk;
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = edge;
-  myInfo.myNbEdges++;
 
-//  if (edge && !registerElement(ID, edge))
-//  {
-//    RemoveElement(edge, false);
-//    edge = NULL;
-//  }
-  return edge;
+  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;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -409,7 +340,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * n2,
                                   const SMDS_MeshNode * n3)
 {
-  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -418,9 +349,9 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 
 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);
+  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);
 }
@@ -434,14 +365,16 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n3,
                                         int ID)
 {
-  //MESSAGE("AddFaceWithID " << ID)
-  SMDS_MeshFace * face=createTriangle(n1, n2, n3, ID);
+  if ( !n1 || !n2 || !n3 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-//  if (face && !registerElement(ID, face)) {
-//    RemoveElement(face, false);
-//    face = NULL;
-//  }
-  return face;
+  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;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -454,7 +387,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * n3,
                                   const SMDS_MeshNode * n4)
 {
-  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -467,12 +400,12 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
                                         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 || !node2 || !node3 || !node4) return NULL;
+  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);
 }
 
@@ -486,103 +419,16 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n4,
                                         int ID)
 {
-  //MESSAGE("AddFaceWithID " << ID);
-  SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4, ID);
-
-//  if (face && !registerElement(ID, face)) {
-//    RemoveElement(face, false);
-//    face = NULL;
-//  }
-  return face;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Add a triangle defined by its edges. An ID is automatically assigned to the
-/// Created face
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
-                                  const SMDS_MeshEdge * e2,
-                                  const SMDS_MeshEdge * e3)
-{
-  if (!hasConstructionEdges())
-    return NULL;
-     //MESSAGE("AddFaceWithID");
- return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Add a triangle defined by its edges
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
-                                        const SMDS_MeshEdge * e2,
-                                        const SMDS_MeshEdge * e3,
-                                        int ID)
-{
-  if (!hasConstructionEdges())
-    return NULL;
-  if ( !e1 || !e2 || !e3 ) return 0;
-
-  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  MESSAGE("AddFaceWithID" << ID);
-
-  SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = face;
-  myInfo.myNbTriangles++;
-
-  if (!registerElement(ID, face)) {
-    registerElement(myElementIDFactory->GetFreeID(), face);
-    //RemoveElement(face, false);
-    //face = NULL;
-  }
-  return face;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Add a quadrangle defined by its edges. An ID is automatically assigned to the
-/// Created face
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
-                                  const SMDS_MeshEdge * e2,
-                                  const SMDS_MeshEdge * e3,
-                                  const SMDS_MeshEdge * e4)
-{
-  if (!hasConstructionEdges())
-    return NULL;
-     //MESSAGE("AddFaceWithID" );
- return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Add a quadrangle defined by its edges
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
-                                        const SMDS_MeshEdge * e2,
-                                        const SMDS_MeshEdge * e3,
-                                        const SMDS_MeshEdge * e4,
-                                        int ID)
-{
-  if (!hasConstructionEdges())
-    return NULL;
-  MESSAGE("AddFaceWithID" << ID);
-  if ( !e1 || !e2 || !e3 || !e4 ) return 0;
+  if ( !n1 || !n2 || !n3 || !n4 ) return 0;
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = face;
-  myInfo.myNbQuadrangles++;
 
-  if (!registerElement(ID, face))
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    registerElement(myElementIDFactory->GetFreeID(), face);
-    //RemoveElement(face, false);
-    //face = NULL;
+    cell->init( SMDSEntity_Quadrangle, /*nbNodes=*/4, n1, n2, n3, n4 );
+    myInfo.myNbQuadrangles++;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
-  return face;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -595,11 +441,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n3,
                                       const SMDS_MeshNode * n4)
 {
-  int ID = myElementIDFactory->GetFreeID();
-    //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, myCellFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -615,12 +457,11 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
                                              int idnode4,
                                              int ID)
 {
-    //MESSAGE("AddVolumeWithID" << 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);
+  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);
 }
@@ -637,51 +478,16 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n4,
                                             int ID)
 {
-  //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume* volume = 0;
-  if ( !n1 || !n2 || !n3 || !n4) return volume;
+  if ( !n1 || !n2 || !n3 || !n4 ) return 0;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionFaces()) {
-    SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
-    SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
-    SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
-    SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
-    volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
-    myInfo.myNbTetras++;
-  }
-  else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else {
-    // --- retrieve nodes ID
-    myNodeIds.resize(4);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n3->getVtkId(); // order SMDS-->VTK
-    myNodeIds[2] = n2->getVtkId();
-    myNodeIds[3] = n4->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
+
+  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 );
   }
-
-  //  if (!registerElement(ID, volume)) {
-  //    RemoveElement(volume, false);
-  //    volume = NULL;
-  //  }
-  return volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -696,11 +502,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n4,
                                       const SMDS_MeshNode * n5)
 {
-  int ID = myElementIDFactory->GetFreeID();
-    //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume * v = SMDS_Mesh::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() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -718,13 +520,12 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
                                              int idnode5,
                                              int ID)
 {
-    //MESSAGE("AddVolumeWithID " << 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);
+  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);
 }
@@ -743,52 +544,16 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n5,
                                             int ID)
 {
-  //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume* volume = 0;
-  if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 ) return 0;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionFaces()) {
-    SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
-    SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
-    SMDS_MeshFace * f3=FindFaceOrCreate(n2,n3,n5);
-    SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
-    volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
-    myInfo.myNbPyramids++;
-  }
-  else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else {
-    // --- retrieve nodes ID
-    myNodeIds.resize(5);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n4->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n2->getVtkId();
-    myNodeIds[4] = n5->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
+
+  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 );
   }
-
-  //  if (!registerElement(ID, volume)) {
-  //    RemoveElement(volume, false);
-  //    volume = NULL;
-  //  }
-  return volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -804,11 +569,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n5,
                                       const SMDS_MeshNode * n6)
 {
-  int ID = myElementIDFactory->GetFreeID();
-    //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume * v = SMDS_Mesh::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);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -827,15 +589,13 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
                                              int idnode6,
                                              int ID)
 {
-    //MESSAGE("AddVolumeWithID " << 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 || !node2 || !node3 || !node4 || !node5 || !node6) return NULL;
+  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);
 }
 
@@ -854,54 +614,16 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n6,
                                             int ID)
 {
-  //MESSAGE("AddVolumeWithID " << ID);
-  SMDS_MeshVolume* volume = 0;
-  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 ) return 0;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionFaces()) {
-    SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
-    SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
-    SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n5,n2);
-    SMDS_MeshFace * f4=FindFaceOrCreate(n2,n5,n6,n3);
-    SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
-    volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
-    myInfo.myNbPrisms++;
-  }
-  else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else {
-    // --- retrieve nodes ID
-    myNodeIds.resize(6);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n2->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n4->getVtkId();
-    myNodeIds[4] = n5->getVtkId();
-    myNodeIds[5] = n6->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
+
+  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 );
   }
-
-  //  if (!registerElement(ID, volume)) {
-  //    RemoveElement(volume, false);
-  //    volume = NULL;
-  //  }
-  return volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -922,12 +644,9 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n11,
                                       const SMDS_MeshNode * n12)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
-                                                   n7, n8, n9, n10, n11, n12,
-                                                   ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+                                    n7, n8, n9, n10, n11, n12,
+                                    myCellFactory->GetFreeID() );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -951,18 +670,18 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
                                              int idnode12,
                                              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);
-  SMDS_MeshNode *node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
-  SMDS_MeshNode *node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
-  SMDS_MeshNode *node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
-  SMDS_MeshNode *node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
-  SMDS_MeshNode *node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
-  SMDS_MeshNode *node9 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode9);
-  SMDS_MeshNode *node10 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode10);
-  SMDS_MeshNode *node11 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode11);
-  SMDS_MeshNode *node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode12);
+  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);
@@ -993,46 +712,15 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
      !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
     return volume;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionFaces()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else {
-    // --- retrieve nodes ID
-    myNodeIds.resize(12);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n6->getVtkId();
-    myNodeIds[2] = n5->getVtkId();
-    myNodeIds[3] = n4->getVtkId();
-    myNodeIds[4] = n3->getVtkId();
-    myNodeIds[5] = n2->getVtkId();
-
-    myNodeIds[6] = n7->getVtkId();
-    myNodeIds[7] = n12->getVtkId();
-    myNodeIds[8] = n11->getVtkId();
-    myNodeIds[9] = n10->getVtkId();
-    myNodeIds[10] = n9->getVtkId();
-    myNodeIds[11] = n8->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
+
+  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 volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1050,10 +738,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n7,
                                       const SMDS_MeshNode * n8)
 {
-  int ID = myElementIDFactory->GetFreeID();
- SMDS_MeshVolume * v = SMDS_Mesh::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);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1074,18 +760,15 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
                                              int idnode8,
                                              int ID)
 {
-    //MESSAGE("AddVolumeWithID " << 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 || !node2 || !node3 || !node4 || !node5 || !node6 || !node7 || !node8)
-    return NULL;
+  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);
 }
@@ -1108,214 +791,31 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n8,
                                             int ID)
 {
-    //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionFaces()) {
-    SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
-    SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
-    SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n8,n5);
-    SMDS_MeshFace * f4=FindFaceOrCreate(n1,n2,n6,n5);
-    SMDS_MeshFace * f5=FindFaceOrCreate(n2,n3,n7,n6);
-    SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
-    volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
-    myInfo.myNbHexas++;
-  }
-  else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else {
-    // --- retrieve nodes ID
-    myNodeIds.resize(8);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n4->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n2->getVtkId();
-    myNodeIds[4] = n5->getVtkId();
-    myNodeIds[5] = n8->getVtkId();
-    myNodeIds[6] = n7->getVtkId();
-    myNodeIds[7] = n6->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
-    myInfo.myNbHexas++;
-  }
-
-  //  if (!registerElement(ID, volume)) {
-  //    RemoveElement(volume, false);
-  //    volume = NULL;
-  //  }
-  return volume;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron defined by its faces and add it to the mesh.
-///@return The created tetrahedron
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
-                                      const SMDS_MeshFace * f2,
-                                      const SMDS_MeshFace * f3,
-                                      const SMDS_MeshFace * f4)
-{
-    //MESSAGE("AddVolumeWithID");
-  if (!hasConstructionFaces())
-    return NULL;
-  return AddVolumeWithID(f1,f2,f3,f4, myElementIDFactory->GetFreeID());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron defined by its faces 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_MeshFace * f1,
-                                            const SMDS_MeshFace * f2,
-                                            const SMDS_MeshFace * f3,
-                                            const SMDS_MeshFace * f4,
-                                            int ID)
-{
-  MESSAGE("AddVolumeWithID" << ID);
-  if (!hasConstructionFaces())
-    return NULL;
-  if ( !f1 || !f2 || !f3 || !f4) return 0;
-  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volume;
-  myInfo.myNbTetras++;
-
-  if (!registerElement(ID, volume)) {
-    registerElement(myElementIDFactory->GetFreeID(), volume);
-    //RemoveElement(volume, false);
-    //volume = NULL;
-  }
-  return volume;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid defined by its faces and add it to the mesh.
-///@return The created pyramid
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
-                                      const SMDS_MeshFace * f2,
-                                      const SMDS_MeshFace * f3,
-                                      const SMDS_MeshFace * f4,
-                                      const SMDS_MeshFace * f5)
-{
-     //MESSAGE("AddVolumeWithID");
- if (!hasConstructionFaces())
-    return NULL;
-  return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid defined by its faces and add it to the mesh.
-///@param ID The ID of the new volume
-///@return The created pyramid
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
-                                            const SMDS_MeshFace * f2,
-                                            const SMDS_MeshFace * f3,
-                                            const SMDS_MeshFace * f4,
-                                            const SMDS_MeshFace * f5,
-                                            int ID)
-{
-  MESSAGE("AddVolumeWithID" << ID);
-  if (!hasConstructionFaces())
-    return NULL;
-  if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
-  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volume;
-  myInfo.myNbPyramids++;
-
-  if (!registerElement(ID, volume)) {
-    registerElement(myElementIDFactory->GetFreeID(), volume);
-    //RemoveElement(volume, false);
-    //volume = NULL;
-  }
-  return volume;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new prism defined by its faces and add it to the mesh.
-///@return The created prism
-///////////////////////////////////////////////////////////////////////////////
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
-                                      const SMDS_MeshFace * f2,
-                                      const SMDS_MeshFace * f3,
-                                      const SMDS_MeshFace * f4,
-                                      const SMDS_MeshFace * f5,
-                                      const SMDS_MeshFace * f6)
-{
-     //MESSAGE("AddVolumeWithID" );
- if (!hasConstructionFaces())
-    return NULL;
-  return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a new prism defined by its faces 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_MeshFace * f1,
-                                            const SMDS_MeshFace * f2,
-                                            const SMDS_MeshFace * f3,
-                                            const SMDS_MeshFace * f4,
-                                            const SMDS_MeshFace * f5,
-                                            const SMDS_MeshFace * f6,
-                                            int ID)
-{
-  MESSAGE("AddVolumeWithID" << ID);
-  if (!hasConstructionFaces())
-    return NULL;
-  if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
-  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volume;
-  myInfo.myNbPrisms++;
-
-  if (!registerElement(ID, volume)) {
-    registerElement(myElementIDFactory->GetFreeID(), volume);
-    //RemoveElement(volume, false);
-    //volume = NULL;
+  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 volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Add a polygon defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
-                                                  const int           ID)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+                                                  const int               ID)
 {
   int nbNodes = nodes_ids.size();
-  vector<const SMDS_MeshNode*> nodes (nbNodes);
+  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
   for (int i = 0; i < nbNodes; i++) {
-    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    nodes[i] = myNodeFactory->FindNode( nodes_ids[i] );
     if (!nodes[i]) return NULL;
   }
   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
@@ -1326,39 +826,18 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace*
-SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
-                                   const int                            ID)
+SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+                                   const int                                 ID)
 {
-  SMDS_MeshFace * face;
-
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if (hasConstructionEdges())
-  {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else
-  {
-    myNodeIds.resize( nodes.size() );
-    for ( size_t i = 0; i < nodes.size(); ++i )
-      myNodeIds[i] = nodes[i]->getVtkId();
 
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->initPoly(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
+  {
+    cell->init( SMDSEntity_Polygon, nodes );
     myInfo.myNbPolygons++;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
-
-  return face;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1366,21 +845,21 @@ SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
 /// An ID is automatically affected to the created face.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
 {
-  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Add a quadratic polygon defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<int> & nodes_ids,
-                                                      const int           ID)
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int> & nodes_ids,
+                                                      const int                ID)
 {
-  vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
+  std::vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
   for ( size_t i = 0; i < nodes.size(); i++) {
-    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
     if (!nodes[i]) return NULL;
   }
   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
@@ -1391,37 +870,17 @@ SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<int> & nodes_
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace*
-SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
-                                       const int                            ID)
+SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
+                                       const int                                 ID)
 {
-  SMDS_MeshFace * face;
-
   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if (hasConstructionEdges())
-  {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    myNodeIds.resize( nodes.size() );
-    for ( size_t i = 0; i < nodes.size(); ++i )
-      myNodeIds[i] = nodes[i]->getVtkId();
-
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->initQuadPoly(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+    cell->init( SMDSEntity_Quad_Polygon, nodes );
     myInfo.myNbQuadPolygons++;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
-  return face;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1429,9 +888,9 @@ SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & node
 /// An ID is automatically affected to the created face.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
 {
-  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1441,15 +900,14 @@ SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const vector<const SMDS_MeshNode
 /// or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
-                             (const vector<int> & nodes_ids,
-                              const vector<int> & quantities,
-                              const int           ID)
+SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int> & nodes_ids,
+                                                        const std::vector<int> & quantities,
+                                                        const int                ID)
 {
   int nbNodes = nodes_ids.size();
-  vector<const SMDS_MeshNode*> nodes (nbNodes);
+  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
   for (int i = 0; i < nbNodes; i++) {
-    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
     if (!nodes[i]) return NULL;
   }
   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
@@ -1462,61 +920,22 @@ SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume*
-SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
-                                      const vector<int>                 & quantities,
+SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                      const std::vector<int>                 & quantities,
                                       const int                           ID)
 {
-  SMDS_MeshVolume* volume = 0;
   if ( nodes.empty() || quantities.empty() )
     return NULL;
   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if (hasConstructionFaces())
-  {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else if (hasConstructionEdges())
-  {
-    MESSAGE("Error : Not implemented");
-    return NULL;
-  }
-  else
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    //#ifdef VTK_HAVE_POLYHEDRON
-    //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID);
-    myNodeIds.resize( nodes.size() );
-    for ( size_t i = 0; i < nodes.size(); ++i )
-      myNodeIds[i] = nodes[i]->getVtkId();
-
-    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-    volvtk->initPoly(myNodeIds, quantities, this);
-    if (!this->registerElement(ID, volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-    volume = volvtk;
-    //#else
-    //      MESSAGE("AddPolyhedralVolumeWithID smds " << ID);
-    //      for ( int i = 0; i < nodes.size(); ++i )
-    //      if ( !nodes[ i ] ) return 0;
-    //      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
-    //#endif
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = volume;
+    SMDS_MeshVolume* volume = static_cast<SMDS_MeshVolume*>( cell );
+    volume->init( nodes, quantities );
     myInfo.myNbPolyhedrons++;
+    return volume;
   }
-
-  //#ifndef VTK_HAVE_POLYHEDRON
-  //  if (!registerElement(ID, volume))
-  //    {
-  //      registerElement(myElementIDFactory->GetFreeID(), volume);
-  //      //RemoveElement(volume, false);
-  //      //volume = NULL;
-  //    }
-  //#endif
-  return volume;
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1525,156 +944,31 @@ SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
-                            (const vector<const SMDS_MeshNode*> & nodes,
                            const vector<int>                  & quantities)
+(const std::vector<const SMDS_MeshNode*> & nodes,
const std::vector<int>                  & quantities)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
-  if (v == NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  int ID = myCellFactory->GetFreeID();
+  return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
 }
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeFromVtkIdsWithID(vtkNodeIds, ID);
-  if (v == NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
-}
-
-SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
-{
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(vtkNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-      myVolumePool->destroy(volvtk);
-      return 0;
-    }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  vtkIdType aVtkType = volvtk->GetVtkType();
-  switch (aVtkType)
-  {
-    case VTK_TETRA:
-      myInfo.myNbTetras++;
-      break;
-    case VTK_PYRAMID:
-      myInfo.myNbPyramids++;
-      break;
-    case VTK_WEDGE:
-      myInfo.myNbPrisms++;
-      break;
-    case VTK_HEXAHEDRON:
-      myInfo.myNbHexas++;
-      break;
-    case VTK_QUADRATIC_TETRA:
-      myInfo.myNbQuadTetras++;
-      break;
-    case VTK_QUADRATIC_PYRAMID:
-      myInfo.myNbQuadPyramids++;
-      break;
-    case VTK_QUADRATIC_WEDGE:
-      myInfo.myNbQuadPrisms++;
-      break;
-    case VTK_QUADRATIC_HEXAHEDRON:
-      myInfo.myNbQuadHexas++;
-      break;
-//#ifdef VTK_HAVE_POLYHEDRON
-    case VTK_POLYHEDRON:
-      myInfo.myNbPolyhedrons++;
-      break;
-//#endif
-    default:
-      myInfo.myNbPolyhedrons++;
-      break;
-  }
-  return volvtk;
+  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)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshFace * f = SMDS_Mesh::AddFaceFromVtkIdsWithID(vtkNodeIds, ID);
-  if (f == NULL) myElementIDFactory->ReleaseID(ID);
+  SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
+  SMDS_MeshFace *   f = static_cast<SMDS_MeshFace*>( cell );
+  f->init( vtkNodeIds );
+  myInfo.add( cell );
   return f;
 }
 
-SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
-{
-  SMDS_VtkFace *facevtk = myFacePool->getNew();
-  facevtk->init(vtkNodeIds, this);
-  if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = facevtk;
-  vtkIdType aVtkType = facevtk->GetVtkType();
-  switch (aVtkType)
-  {
-    case VTK_TRIANGLE:
-      myInfo.myNbTriangles++;
-      break;
-    case VTK_QUAD:
-      myInfo.myNbQuadrangles++;
-      break;
-    case VTK_QUADRATIC_TRIANGLE:
-      myInfo.myNbQuadTriangles++;
-      break;
-    case VTK_QUADRATIC_QUAD:
-      myInfo.myNbQuadQuadrangles++;
-      break;
-    case VTK_BIQUADRATIC_QUAD:
-      myInfo.myNbBiQuadQuadrangles++;
-      break;
-    case VTK_BIQUADRATIC_TRIANGLE:
-      myInfo.myNbBiQuadTriangles++;
-      break;
-    case VTK_POLYGON:
-      myInfo.myNbPolygons++;
-      break;
-     default:
-      myInfo.myNbPolygons++;
-  }
-  return facevtk;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Registers element with the given ID, maintains inverse connections
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element)
-{
-  //MESSAGE("registerElement " << ID);
-  if ((ID >=0) && (ID < myCells.size()) && myCells[ID]) // --- already bound
-  {
-    MESSAGE(" ------------------ already bound "<< ID << " " << myCells[ID]->getVtkId());
-    return false;
-  }
-
-  element->myID = ID;
-  element->myMeshId = myMeshId;
-
-  SMDS_MeshCell *cell = dynamic_cast<SMDS_MeshCell*>(element);
-  MYASSERT(cell);
-  int vtkId = cell->getVtkId();  
-  if (vtkId == -1)
-    vtkId = myElementIDFactory->SetInVtkGrid(element);
-
-  if (vtkId >= myCellIdVtkToSmds.size()) // --- resize local vector
-  {
-//     MESSAGE(" --------------------- resize myCellIdVtkToSmds " << vtkId << " --> " << vtkId + SMDS_Mesh::chunkSize);
-    myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1);
-  }
-  myCellIdVtkToSmds[vtkId] = ID;
-
-  myElementIDFactory->updateMinMax(ID);
-  return true;
-}
-
 //=======================================================================
 //function : MoveNode
 //purpose  : 
@@ -1691,14 +985,7 @@ void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
 ///////////////////////////////////////////////////////////////////////////////
 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
 {
-  if (ID < 1 || ID >= myNodes.size())
-  {
-//     MESSAGE("------------------------------------------------------------------------- ");
-//     MESSAGE("----------------------------------- bad ID " << ID << " " << myNodes.size());
-//     MESSAGE("------------------------------------------------------------------------- ");
-    return 0;
-  }
-  return (const SMDS_MeshNode *)myNodes[ID];
+  return myNodeFactory->FindNode( ID );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1706,119 +993,12 @@ const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
 ///////////////////////////////////////////////////////////////////////////////
 const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
 {
-  // TODO if needed use mesh->nodeIdFromVtkToSmds
-  if (vtkId < 0 || vtkId >= (myNodes.size() -1))
-  {
-    MESSAGE("------------------------------------------------------------------------- ");
-    MESSAGE("---------------------------- bad VTK ID " << vtkId << " " << myNodes.size());
-    MESSAGE("------------------------------------------------------------------------- ");
-    return 0;
-  }
-  return (const SMDS_MeshNode *)myNodes[vtkId+1];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///Create a triangle and add it to the current mesh. This method do not bind an
-///ID to the create triangle.
-///////////////////////////////////////////////////////////////////////////////
-SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
-                                          const SMDS_MeshNode * node2,
-                                          const SMDS_MeshNode * node3,
-                                          int ID)
-{
-  if ( !node1 || !node2 || !node3) return 0;
-  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionEdges())
-  {
-    SMDS_MeshEdge *edge1, *edge2, *edge3;
-    edge1=FindEdgeOrCreate(node1,node2);
-    edge2=FindEdgeOrCreate(node2,node3);
-    edge3=FindEdgeOrCreate(node3,node1);
-
-    //int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
-    SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
-    myInfo.myNbTriangles++;
-    return face;
-  }
-  else
-  {
-    // --- retrieve nodes ID
-    myNodeIds.resize(3);
-    myNodeIds[0] = node1->getVtkId();
-    myNodeIds[1] = node2->getVtkId();
-    myNodeIds[2] = node3->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
-    //MESSAGE("createTriangle " << ID << " " << face);
-    myInfo.myNbTriangles++;
-    return face;
-  }
+  return myNodeFactory->FindNode( vtkId + 1 );
 }
 
-///////////////////////////////////////////////////////////////////////////////
-///Create a quadrangle and add it to the current mesh. This methode do not bind
-///a ID to the create triangle.
-///////////////////////////////////////////////////////////////////////////////
-SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
-                                            const SMDS_MeshNode * node2,
-                                            const SMDS_MeshNode * node3,
-                                            const SMDS_MeshNode * node4,
-                                            int ID)
+const SMDS_MeshElement * SMDS_Mesh::FindElementVtk(int IDelem) const
 {
-  if ( !node1 || !node2 || !node3 || !node4 ) return 0;
-  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-  if(hasConstructionEdges())
-  {
-    //MESSAGE("createQuadrangle hasConstructionEdges "<< ID);
-    SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
-    edge1=FindEdgeOrCreate(node1,node2);
-    edge2=FindEdgeOrCreate(node2,node3);
-    edge3=FindEdgeOrCreate(node3,node4);
-    edge4=FindEdgeOrCreate(node4,node1);
-
-    SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
-    myInfo.myNbQuadrangles++;
-    return face;
-  }
-  else
-  {
-    // --- retrieve nodes ID
-    myNodeIds.resize(4);
-    myNodeIds[0] = node1->getVtkId();
-    myNodeIds[1] = node2->getVtkId();
-    myNodeIds[2] = node3->getVtkId();
-    myNodeIds[3] = node4->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
-    myInfo.myNbQuadrangles++;
-    return face;
-  }
+  return myCellFactory->FindElement( FromVtkToSmds( IDelem ));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1827,50 +1007,9 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
 
 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 {
-  MESSAGE("RemoveNode");
   RemoveElement(node, true);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Remove an edge and all the elements which own this edge
-///////////////////////////////////////////////////////////////////////////////
-
-void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
-{
-  MESSAGE("Remove0DElement");
-  RemoveElement(elem0d,true);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Remove an edge and all the elements which own this edge
-///////////////////////////////////////////////////////////////////////////////
-
-void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
-{
-  MESSAGE("RemoveEdge");
-  RemoveElement(edge,true);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Remove an face and all the elements which own this face
-///////////////////////////////////////////////////////////////////////////////
-
-void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
-{
-  MESSAGE("RemoveFace");
-  RemoveElement(face, true);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Remove a volume
-///////////////////////////////////////////////////////////////////////////////
-
-void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
-{
-  MESSAGE("RemoveVolume");
-  RemoveElement(volume, true);
-}
-
 //=======================================================================
 //function : RemoveFromParent
 //purpose  :
@@ -1891,7 +1030,7 @@ bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
 {
   bool found = false;
 
-  list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+  std::list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
   for (; itmsh!=myChildren.end() && !found; itmsh++)
   {
     SMDS_Mesh * submesh = *itmsh;
@@ -1914,29 +1053,27 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
                                    const SMDS_MeshNode    * nodes[],
                                    const int                nbnodes)
 {
-  MESSAGE("SMDS_Mesh::ChangeElementNodes");
-  // keep current nodes of elem
-  set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
+  // keep current nodes of element
+  std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
 
   // change nodes
   bool Ok = false;
-  SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
-  if (cell)
-  {
-    Ok = cell->vtkOrder(nodes, nbnodes);
+  if ( SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element))
     Ok = cell->ChangeNodes(nodes, nbnodes);
-  }
 
-  if ( Ok ) { // update InverseElements
+  if ( Ok )
+    setMyModified();
 
-    set<const SMDS_MeshNode*>::iterator it;
+  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( cell );
+        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( element );
       else
         // remove from oldNodes a node that remains in elem
         oldNodes.erase( it );
@@ -1945,84 +1082,13 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
     {
       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
-      n->RemoveInverseElement( cell );
-    }
-  }
-
-  return Ok;
-}
-
-//=======================================================================
-//function : ChangePolyhedronNodes
-//purpose  : to change nodes of polyhedral volume
-//=======================================================================
-bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
-                                       const vector<const SMDS_MeshNode*>& nodes,
-                                       const vector<int>                 & quantities)
-{
-  if (elem->GetType() != SMDSAbs_Volume) {
-    MESSAGE("WRONG ELEM TYPE");
-    return false;
-  }
-
-  const SMDS_VtkVolume* vol = dynamic_cast<const SMDS_VtkVolume*>(elem);
-  if (!vol) {
-    return false;
-  }
-
-  // keep current nodes of elem
-  set<const SMDS_MeshElement*> oldNodes;
-  SMDS_ElemIteratorPtr itn = elem->nodesIterator();
-  while (itn->more()) {
-    oldNodes.insert(itn->next());
-  }
-
-  // change nodes
-  // TODO remove this function
-  //bool Ok = const_cast<SMDS_VtkVolume*>(vol)->ChangeNodes(nodes, quantities);
-  bool Ok = false;
-  if (!Ok) {
-    return false;
-  }
-
-  // update InverseElements
-
-  // AddInverseElement to new nodes
-  int nbnodes = nodes.size();
-  set<const SMDS_MeshElement*>::iterator it;
-  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(elem);
-    } else {
-      // remove from oldNodes a node that remains in elem
-      oldNodes.erase(it);
+      n->RemoveInverseElement( element );
     }
   }
 
-  // RemoveInverseElement from the nodes removed from elem
-  for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
-    SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
-      (const_cast<SMDS_MeshElement *>( *it ));
-    n->RemoveInverseElement(elem);
-  }
-
   return Ok;
 }
 
-
-//=======================================================================
-//function : Find0DElement
-//purpose  :
-//=======================================================================
-const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(int idnode) const
-{
-  const SMDS_MeshNode * node = FindNode(idnode);
-  if(node == NULL) return NULL;
-  return Find0DElement(node);
-}
-
 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
 {
   if (!node) return 0;
@@ -2037,18 +1103,6 @@ const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
   return toReturn;
 }
 
-//=======================================================================
-//function : FindBall
-//purpose  :
-//=======================================================================
-
-const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
-{
-  const SMDS_MeshNode * node = FindNode(idnode);
-  if(node == NULL) return NULL;
-  return FindBall(node);
-}
-
 const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
 {
   if (!node) return 0;
@@ -2062,49 +1116,12 @@ const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
   return toReturn;
 }
 
-//=======================================================================
-//function : Find0DElementOrCreate
-//purpose  :
-//=======================================================================
-//SMDS_Mesh0DElement* SMDS_Mesh::Find0DElementOrCreate(const SMDS_MeshNode * node)
-//{
-//  if (!node) return 0;
-//  SMDS_Mesh0DElement * toReturn = NULL;
-//  toReturn = const_cast<SMDS_Mesh0DElement*>(Find0DElement(node));
-//  if (toReturn == NULL) {
-//    //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
-//    toReturn = new SMDS_Mesh0DElement(node);
-//    my0DElements.Add(toReturn);
-//    myInfo.myNb0DElements++;
-//  }
-//  return toReturn;
-//}
-
-
-//=======================================================================
-//function : FindEdge
-//purpose  :
-//=======================================================================
-
-const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
-{
-  const SMDS_MeshNode * node1=FindNode(idnode1);
-  const SMDS_MeshNode * node2=FindNode(idnode2);
-  if((node1==NULL)||(node2==NULL)) return NULL;
-  return FindEdge(node1,node2);
-}
-
-//#include "Profiler.h"
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2)
 {
   if ( !node1 ) return 0;
   const SMDS_MeshEdge * toReturn=NULL;
-  //PROFILER_Init();
-  //PROFILER_Set();
   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
-  //PROFILER_Get(0);
-  //PROFILER_Set();
   while(it1->more()) {
     const SMDS_MeshElement * e = it1->next();
     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
@@ -2112,60 +1129,9 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
       break;
     }
   }
-  //PROFILER_Get(1);
-  return toReturn;
-}
-
-
-//=======================================================================
-//function : FindEdgeOrCreate
-//purpose  :
-//=======================================================================
-
-SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
-                                           const SMDS_MeshNode * node2)
-{
-  if ( !node1 || !node2) return 0;
-  SMDS_MeshEdge * toReturn=NULL;
-  toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
-  if(toReturn==NULL) {
-    if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
-    int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
-    adjustmyCellsCapacity(ID);
-    myNodeIds.resize(2);
-    myNodeIds[0] = node1->getVtkId();
-    myNodeIds[1] = node2->getVtkId();
-
-    SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
-    edgevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,edgevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
-      myEdgePool->destroy(edgevtk);
-      return 0;
-    }
-    toReturn = edgevtk;
-    myCells[ID] = toReturn;
-    myInfo.myNbEdges++;
-  }
   return toReturn;
 }
 
-
-//=======================================================================
-//function : FindEdge
-//purpose  :
-//=======================================================================
-
-const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
-                                         int idnode3) const
-{
-  const SMDS_MeshNode * node1=FindNode(idnode1);
-  const SMDS_MeshNode * node2=FindNode(idnode2);
-  const SMDS_MeshNode * node3=FindNode(idnode3);
-  return FindEdge(node1,node2,node3);
-}
-
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2,
                                          const SMDS_MeshNode * node3)
@@ -2193,21 +1159,11 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
   return 0;
 }
 
-
 //=======================================================================
 //function : FindFace
 //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);
-  return FindFace(node1, node2, node3);
-}
-
 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3)
@@ -2235,35 +1191,11 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
   return 0;
 }
 
-SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
-                                           const SMDS_MeshNode *node2,
-                                           const SMDS_MeshNode *node3)
-{
-  SMDS_MeshFace * toReturn=NULL;
-  toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
-  if(toReturn==NULL) {
-    int ID = myElementIDFactory->GetFreeID();
-    toReturn = createTriangle(node1,node2,node3, ID);
-  }
-  return toReturn;
-}
-
-
 //=======================================================================
 //function : FindFace
 //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);
-  return FindFace(node1, node2, node3, node4);
-}
-
 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3,
@@ -2293,39 +1225,11 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
   return 0;
 }
 
-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) {
-    int ID = myElementIDFactory->GetFreeID();
-    toReturn=createQuadrangle(node1,node2,node3,node4,ID);
-  }
-  return toReturn;
-}
-
-
 //=======================================================================
 //function : FindFace
 //purpose  :quadratic triangle
 //=======================================================================
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
-                                         int idnode3, int idnode4,
-                                         int idnode5, int idnode6) const
-{
-  const SMDS_MeshNode * node1 = FindNode(idnode1);
-  const SMDS_MeshNode * node2 = FindNode(idnode2);
-  const SMDS_MeshNode * node3 = FindNode(idnode3);
-  const SMDS_MeshNode * node4 = FindNode(idnode4);
-  const SMDS_MeshNode * node5 = FindNode(idnode5);
-  const SMDS_MeshNode * node6 = FindNode(idnode6);
-  return FindFace(node1, node2, node3, node4, node5, node6);
-}
-
 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3,
@@ -2365,22 +1269,6 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
 //purpose  : quadratic quadrangle
 //=======================================================================
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
-                                         int idnode3, int idnode4,
-                                         int idnode5, int idnode6,
-                                         int idnode7, int idnode8) const
-{
-  const SMDS_MeshNode * node1 = FindNode(idnode1);
-  const SMDS_MeshNode * node2 = FindNode(idnode2);
-  const SMDS_MeshNode * node3 = FindNode(idnode3);
-  const SMDS_MeshNode * node4 = FindNode(idnode4);
-  const SMDS_MeshNode * node5 = FindNode(idnode5);
-  const SMDS_MeshNode * node6 = FindNode(idnode6);
-  const SMDS_MeshNode * node7 = FindNode(idnode7);
-  const SMDS_MeshNode * node8 = FindNode(idnode8);
-  return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
-}
-
 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3,
@@ -2426,16 +1314,7 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
 
 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 {
-  if ((IDelem <= 0) || IDelem >= myCells.size())
-  {
-    MESSAGE("--------------------------------------------------------------------------------- ");
-    MESSAGE("----------------------------------- bad IDelem " << IDelem << " " << myCells.size());
-    MESSAGE("--------------------------------------------------------------------------------- ");
-    // TODO raise an exception
-    //assert(0);
-    return 0;
-  }
-  return myCells[IDelem];
+  return myCellFactory->FindElement( IDelem );
 }
 
 //=======================================================================
@@ -2443,19 +1322,8 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 //purpose  : find polygon
 //=======================================================================
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
-{
-  int nbnodes = nodes_ids.size();
-  vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
-  for (int inode = 0; inode < nbnodes; inode++) {
-    const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
-    if (node == NULL) return NULL;
-    poly_nodes[inode] = node;
-  }
-  return FindFace(poly_nodes);
-}
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& nodes)
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const std::vector<const SMDS_MeshNode *>& nodes)
 {
   return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
 }
@@ -2471,7 +1339,7 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& n
  */
 //================================================================================
 
-const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
+const SMDS_MeshElement* SMDS_Mesh::FindElement (const std::vector<const SMDS_MeshNode *>& nodes,
                                                 const SMDSAbs_ElementType            type,
                                                 const bool                           noMedium)
 {
@@ -2482,9 +1350,9 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode
     {
       const SMDS_MeshElement* e = itF->next();
       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
-      if ( nbNodesToCheck == nodes.size() )
+      if ( nbNodesToCheck == (int)nodes.size() )
       {
-        for ( int i = 1; e && i < nodes.size(); ++ i )
+        for ( size_t i = 1; e && i < nodes.size(); ++i )
         {
           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
@@ -2498,113 +1366,47 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode
   return NULL;
 }
 
-//=======================================================================
-//function : DumpNodes
-//purpose  :
-//=======================================================================
-
-void SMDS_Mesh::DumpNodes() const
-{
-        MESSAGE("dump nodes of mesh : ");
-        SMDS_NodeIteratorPtr itnode=nodesIterator();
-        while(itnode->more()) ; //MESSAGE(itnode->next());
-}
-
-//=======================================================================
-//function : Dump0DElements
-//purpose  :
-//=======================================================================
-void SMDS_Mesh::Dump0DElements() const
-{
-  MESSAGE("dump 0D elements of mesh : ");
-  SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
-  while(it0d->more()) ; //MESSAGE(it0d->next());
-}
-
-//=======================================================================
-//function : DumpEdges
-//purpose  :
-//=======================================================================
-
-void SMDS_Mesh::DumpEdges() const
-{
-        MESSAGE("dump edges of mesh : ");
-        SMDS_EdgeIteratorPtr itedge=edgesIterator();
-        while(itedge->more()) ; //MESSAGE(itedge->next());
-}
-
-//=======================================================================
-//function : DumpFaces
-//purpose  :
-//=======================================================================
-
-void SMDS_Mesh::DumpFaces() const
-{
-        MESSAGE("dump faces of mesh : ");
-        SMDS_FaceIteratorPtr itface=facesIterator();
-        while(itface->more()) ; //MESSAGE(itface->next());
-}
-
-//=======================================================================
-//function : DumpVolumes
-//purpose  :
-//=======================================================================
-
-void SMDS_Mesh::DumpVolumes() const
-{
-        MESSAGE("dump volumes of mesh : ");
-        SMDS_VolumeIteratorPtr itvol=volumesIterator();
-        while(itvol->more()) ; //MESSAGE(itvol->next());
-}
-
-//=======================================================================
-//function : DebugStats
-//purpose  :
-//=======================================================================
+//================================================================================
+/*!
+ * \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
+ */
+//================================================================================
 
-void SMDS_Mesh::DebugStats() const
+int SMDS_Mesh::GetElementsByNodes(const std::vector<const SMDS_MeshNode *>& nodes,
+                                  std::vector<const SMDS_MeshElement *>&    foundElems,
+                                  const SMDSAbs_ElementType                 type)
 {
-  MESSAGE("Debug stats of mesh : ");
-
-  MESSAGE("===== NODES ====="<<NbNodes());
-  MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
-  MESSAGE("===== EDGES ====="<<NbEdges());
-  MESSAGE("===== FACES ====="<<NbFaces());
-  MESSAGE("===== VOLUMES ====="<<NbVolumes());
-
-  MESSAGE("End Debug stats of mesh ");
-
-  //#ifdef DEB
-
-  SMDS_NodeIteratorPtr itnode=nodesIterator();
-  int sizeofnodes = 0;
-  int sizeoffaces = 0;
-
-  while(itnode->more())
-  {
-    const SMDS_MeshNode *node = itnode->next();
-
-    sizeofnodes += sizeof(*node);
-
-    SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
-    while(it->more())
+  // 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 )
     {
-      const SMDS_MeshElement *me = it->next();
-      sizeofnodes += sizeof(me);
+      n0 = nodes[i];
+      minNbInverse = n0->NbInverseElements( type );
     }
-  }
 
-  SMDS_FaceIteratorPtr itface=facesIterator();
-  while(itface->more())
+  foundElems.clear();
+  if ( n0 )
   {
-    const SMDS_MeshElement *face = itface->next();
-    sizeoffaces += sizeof(*face);
+    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 );
+    }
   }
-
-  MESSAGE("total size of node elements = " << sizeofnodes);;
-  MESSAGE("total size of face elements = " << sizeoffaces);;
-
-  //#endif
+  return foundElems.size();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2612,12 +1414,16 @@ void SMDS_Mesh::DebugStats() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbNodes() const
 {
-        //MESSAGE(myGrid->GetNumberOfPoints());
-        //MESSAGE(myInfo.NbNodes());
-        //MESSAGE(myNodeMax);
-    return myInfo.NbNodes();
+  return myInfo.NbNodes();
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbElements() const
+{
+  return myInfo.NbElements();
+}
 ///////////////////////////////////////////////////////////////////////////////
 /// Return the number of 0D elements
 ///////////////////////////////////////////////////////////////////////////////
@@ -2673,41 +1479,17 @@ int SMDS_Mesh::NbSubMesh() const
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_Mesh::~SMDS_Mesh()
 {
-  list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
   while(itc!=myChildren.end())
   {
     delete *itc;
     itc++;
   }
 
-  if(myParent==NULL)
-  {
-    delete myNodeIDFactory;
-    delete myElementIDFactory;
-  }
-  else
-  {
-    SMDS_ElemIteratorPtr eIt = elementsIterator();
-    while ( eIt->more() )
-      {
-        const SMDS_MeshElement *elem = eIt->next();
-        myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
-      }
-    SMDS_NodeIteratorPtr itn = nodesIterator();
-    while (itn->more())
-      {
-        const SMDS_MeshNode *node = itn->next();
-        ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
-        myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
-      }
-  }
-  myGrid->Delete();
+  delete myNodeFactory;
+  delete myCellFactory;
 
-  delete myNodePool;
-  delete myVolumePool;
-  delete myFacePool;
-  delete myEdgePool;
-  delete myBallPool;
+  myGrid->Delete();
 }
 
 //================================================================================
@@ -2718,73 +1500,14 @@ SMDS_Mesh::~SMDS_Mesh()
 
 void SMDS_Mesh::Clear()
 {
-  MESSAGE("SMDS_Mesh::Clear");
-  if (myParent!=NULL)
-    {
-    SMDS_ElemIteratorPtr eIt = elementsIterator();
-    while ( eIt->more() )
-      {
-        const SMDS_MeshElement *elem = eIt->next();
-        myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
-      }
-    SMDS_NodeIteratorPtr itn = nodesIterator();
-    while (itn->more())
-      {
-        const SMDS_MeshNode *node = itn->next();
-        myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
-      }
-    }
-  else
-    {
-    myNodeIDFactory->Clear();
-    myElementIDFactory->Clear();
-    }
+  std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
+  for ( ; holder != myElemHolders.end(); ++holder )
+    (*holder)->clear();
 
-  // SMDS_ElemIteratorPtr itv = elementsIterator();
-  // while (itv->more())
-  //   {
-  //     SMDS_MeshElement* elem = (SMDS_MeshElement*)(itv->next());
-  //     SMDSAbs_ElementType aType = elem->GetType();
-  //     switch (aType)
-  //     {
-  //       case SMDSAbs_0DElement:
-  //         delete elem;
-  //         break;
-  //       case SMDSAbs_Edge:
-  //          myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(elem));
-  //         break;
-  //       case SMDSAbs_Face:
-  //         myFacePool->destroy(static_cast<SMDS_VtkFace*>(elem));
-  //         break;
-  //       case SMDSAbs_Volume:
-  //         myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
-  //         break;
-  //       case SMDSAbs_Ball:
-  //         myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
-  //         break;
-  //       default:
-  //         break;
-  //     }
-  //   }
-  myVolumePool->clear();
-  myFacePool->clear();
-  myEdgePool->clear();
-  myBallPool->clear();
-
-  clearVector( myCells );
-  clearVector( myCellIdVtkToSmds );
-
-  SMDS_NodeIteratorPtr itn = nodesIterator();
-  while (itn->more())
-    {
-      SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
-      node->SetPosition(SMDS_SpacePosition::originSpacePosition());
-      //myNodePool->destroy(node);
-    }
-  myNodePool->clear();
-  clearVector( myNodes );
+  myNodeFactory->Clear();
+  myCellFactory->Clear();
 
-  list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
   while(itc!=myChildren.end())
     (*itc)->Clear();
 
@@ -2802,188 +1525,35 @@ void SMDS_Mesh::Clear()
   // 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 /*SMDS_Mesh::chunkSize*/);
+  points->SetNumberOfPoints( 0 );
   myGrid->SetPoints( points );
   points->Delete();
-  myGrid->BuildLinks();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// 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.
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::hasConstructionEdges()
-{
-        return myHasConstructionEdges;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// 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()
-{
-        return myHasConstructionFaces;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Return true if nodes are linked to the finit elements, they are belonging to.
-/// Currently, It always return true.
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::hasInverseElements()
-{
-        return myHasInverseElements;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating construction edges (see hasConstructionEdges)
-/// @param b true to have construction edges, else false.
-///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setConstructionEdges(bool b)
-{
-        myHasConstructionEdges=b;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating construction faces (see hasConstructionFaces)
-/// @param b true to have construction faces, else false.
-///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setConstructionFaces(bool b)
-{
-         myHasConstructionFaces=b;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-/// Make this mesh creating link from nodes to elements (see hasInverseElements)
-/// @param b true to link nodes to elements, else false.
-///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::setInverseElements(bool b)
-{
-  if(!b) MESSAGE("Error : inverseElement=false not implemented");
-  myHasInverseElements=b;
-}
-
-namespace {
-
-  //================================================================================
-  /*!
-   * \brief Iterator on elements in id increasing order
-   */
-  //================================================================================
-
-  template <typename ELEM=const SMDS_MeshElement*>
-  class IdSortedIterator : public SMDS_Iterator<ELEM>
-  {
-    SMDS_MeshElementIDFactory&       myIDFact;
-    int                              myID, myMaxID, myNbFound, myTotalNb;
-    SMDSAbs_ElementType              myType;
-    ELEM                             myElem;
-
-  public:
-    IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
-                     const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
-                     const int                        totalNb)
-      :myIDFact( fact ),
-       myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
-       myType( type ),
-       myElem(0)
-    {
-      next();
-    }
-    bool more()
-    {
-      return myElem;
-    }
-    ELEM next()
-    {
-      ELEM current = myElem;
-
-      for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
-        if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
-            && myElem->GetType() != myType )
-          myElem = 0;
-
-      myNbFound += bool(myElem);
-
-      return current;
-    }
-  };
-
-  //================================================================================
-  /*!
-   * \brief Iterator on vector of elements, possibly being resized while iteration
-   */
-  //================================================================================
-
-  template<typename RETURN_VALUE,
-           typename VECTOR_VALUE=SMDS_MeshCell*,
-           typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
-  class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
-  {
-    const std::vector<VECTOR_VALUE>& _vector;
-    size_t                           _index;
-    bool                             _more;
-    VALUE_FILTER                     _filter;
-  public:
-    ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
-                    const VALUE_FILTER&              filter=VALUE_FILTER() )
-      :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
-    {
-      if ( _more && !_filter( _vector[ _index ]))
-        next();
-    }
-    virtual bool more()
-    {
-      return _more;
-    }
-    virtual RETURN_VALUE next()
-    {
-      if ( !_more ) return NULL;
-      VECTOR_VALUE current = _vector[ _index ];
-      _more = 0;
-      while ( !_more && ++_index < _vector.size() )
-        _more = _filter( _vector[ _index ]);
-      return (RETURN_VALUE) current;
-    }
-  };
+  myGrid->DeleteLinks();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return an iterator on nodes of the current mesh factory
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
+SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
 {
-  // naturally always sorted by ID
-  typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
-  return SMDS_NodeIteratorPtr( new TIterator(myNodes));
+  return myNodeFactory->GetIterator< SMDS_NodeIterator >( new SMDS_MeshElement::NonNullFilter );
 }
 
 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
 {
-  // naturally always sorted by ID
-  typedef ElemVecIterator
-    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
-  return SMDS_ElemIteratorPtr
-    (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
+  return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
+                                                          myInfo.NbElements( type ));
 }
 
 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
 {
   if ( type == SMDSEntity_Node )
   {
-    typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
-    return SMDS_ElemIteratorPtr( new TIterator(myNodes));
+    return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
   }
-  // naturally always sorted by ID
-  typedef ElemVecIterator
-    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
-  return SMDS_ElemIteratorPtr
-    (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
+  return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
+                                                        myInfo.NbElements( type ));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2991,20 +1561,18 @@ SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) c
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 {
-  // naturally always sorted by ID
+  typedef SMDS_ElemIterator TIterator;
   switch ( type ) {
 
   case SMDSAbs_All:
-    return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
+    return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
 
   case SMDSAbs_Node:
-    return SMDS_ElemIteratorPtr
-      ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
+    return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
 
   default:
-    typedef ElemVecIterator
-      < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
-    return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
+    return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
+                                                    myInfo.NbElements( type ));
   }
   return SMDS_ElemIteratorPtr();
 }
@@ -3013,125 +1581,116 @@ SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 ///Return an iterator on edges of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
+SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
 {
-  // naturally always sorted by ID
-  typedef ElemVecIterator
-    < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
-  return SMDS_EdgeIteratorPtr
-    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
+  typedef SMDS_EdgeIterator TIterator;
+  return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
+                                                  myInfo.NbEdges());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///Return an iterator on faces of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
+SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
 {
-  // naturally always sorted by ID
-  typedef ElemVecIterator
-    < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
-  return SMDS_FaceIteratorPtr
-    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
+  typedef SMDS_FaceIterator TIterator;
+  return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
+                                                  myInfo.NbFaces());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///Return an iterator on volumes of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
+SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
+{
+  typedef SMDS_VolumeIterator TIterator;
+  return
+    myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
+                                             myInfo.NbVolumes());
+}
+
+SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
+{
+  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
+}
+
+SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
 {
-  // naturally always sorted by ID
-  typedef ElemVecIterator
-    < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
-  return SMDS_VolumeIteratorPtr
-    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
+  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Do intersection of sets (more than 2)
 ///////////////////////////////////////////////////////////////////////////////
-static 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 finite elements owning the given element: elements
 /// containing all the nodes of the given element, for instance faces and
 /// volumes containing a given edge.
 ///////////////////////////////////////////////////////////////////////////////
-static 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 = new set<const SMDS_MeshElement*>[numberOfSets];
-
-        SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
-
-        int i=0;
-        while(itNodes->more())
-        {
-          const SMDS_MeshElement* node = itNodes->next();
-          MYASSERT(node);
-                const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
-                SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
-
-                //initSet[i]=set<const SMDS_MeshElement*>();
-                while(itFe->more())
-                {
-                  const SMDS_MeshElement* elem = itFe->next();
-                  MYASSERT(elem);
-                  initSet[i].insert(elem);
+  int numberOfSets=element->NbNodes();
+  std::set<const SMDS_MeshElement*> *initSet = new std::set<const SMDS_MeshElement*>[numberOfSets];
 
-                }
+  SMDS_NodeIteratorPtr itNodes = element->nodeIterator();
 
-                i++;
-        }
-        set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
-//         MESSAGE("nb elems " << i << " intersection " << retSet->size());
-        delete [] initSet;
-        return retSet;
+  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
 ///////////////////////////////////////////////////////////////////////////////
-static 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_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
-                itElements++;
-
-                while(itNodes->more())
-                {
-                        const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
-                        SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
-                        set<const SMDS_MeshElement*> s;
-                        while(itFe->more())
-                          s.insert(itFe->next());
-                        if(s==elements) toReturn->insert(n);
-                }
-        }
-        return toReturn;
+  while( itElements != elements.end() )
+  {
+    SMDS_NodeIteratorPtr itNodes = (*itElements)->nodeIterator();
+    itElements++;
+
+    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;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -3140,67 +1699,50 @@ static set<const SMDS_MeshElement*> * getExclusiveNodes(
 ///@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)
+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())
     {
-    case SMDSAbs_Node:
-      MESSAGE("Internal Error: This should not happen");
-      break;
-    case SMDSAbs_0DElement:
+      const SMDS_MeshElement * e=itn->next();
+      if(nodes.find(e)!=nodes.end())
       {
+        setOfChildren.insert(element);
+        break;
       }
-      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;
-                        }
-                }
-                if(hasConstructionEdges())
-                {
-                        SMDS_ElemIteratorPtr ite=element->edgesIterator();
-                        while(ite->more())
-                                addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                }
-        } break;
-    case SMDSAbs_Volume:
-        {
-                if(hasConstructionFaces())
-                {
-                        SMDS_ElemIteratorPtr ite=element->facesIterator();
-                        while(ite->more())
-                                addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                }
-                else if(hasConstructionEdges())
-                {
-                        SMDS_ElemIteratorPtr ite=element->edgesIterator();
-                        while(ite->more())
-                                addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-                }
-        }
     }
+  } 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;
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -3208,10 +1750,10 @@ 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)
+                              const bool               removenodes)
 {
-  list<const SMDS_MeshElement *> removedElems;
-  list<const SMDS_MeshElement *> removedNodes;
+  std::vector<const SMDS_MeshElement *> removedElems;
+  std::vector<const SMDS_MeshElement *> removedNodes;
   RemoveElement( elem, removedElems, removedNodes, removenodes );
 }
 
@@ -3221,166 +1763,93 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
 ///@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,
-                              list<const SMDS_MeshElement *>& removedElems,
-                              list<const SMDS_MeshElement *>& removedNodes,
-                              bool                            removenodes)
+void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
+                              std::vector<const SMDS_MeshElement *>& removedElems,
+                              std::vector<const SMDS_MeshElement *>& removedNodes,
+                              bool                                   removenodes)
 {
-  //MESSAGE("SMDS_Mesh::RemoveElement " << elem->getVtkId() << " " << removenodes);
   // get finite elements built on elem
-  set<const SMDS_MeshElement*> * s1;
+  std::set<const SMDS_MeshElement*> * s1;
   if (    (elem->GetType() == SMDSAbs_0DElement)
-      || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
-      || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
-      ||  (elem->GetType() == SMDSAbs_Volume) )
-    {
-      s1 = new set<const SMDS_MeshElement*> ();
-      s1->insert(elem);
-    }
+          ||  (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)
-  set<const SMDS_MeshElement*> * s2;
+  std::set<const SMDS_MeshElement*> * s2;
   if (elem->GetType() == SMDSAbs_Node) // a node is removed
-    {
-      // do not remove nodes except elem
-      s2 = new set<const SMDS_MeshElement*> ();
-      s2->insert(elem);
-      removenodes = true;
-    }
+  {
+    // 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
-  set<const SMDS_MeshElement*> s3;
-  set<const SMDS_MeshElement*>::iterator it = s1->begin();
+  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++;
-    }
+  {
+    addChildrenWithNodes(s3, *it, *s2);
+    s3.insert(*it);
+    it++;
+  }
   if (elem->GetType() != SMDSAbs_Node)
     s3.insert(elem);
 
   // remove finite and construction elements
-  it = s3.begin();
-  while (it != s3.end())
+  for( it = s3.begin();it != s3.end(); ++it )
+  {
+    // Remove element from <InverseElements> of its nodes
+    SMDS_NodeIteratorPtr itn = (*it)->nodeIterator();
+    while (itn->more())
     {
-      // Remove element from <InverseElements> of its nodes
-      SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
-      while (itn->more())
-        {
-          SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
-          n->RemoveInverseElement((*it));
-        }
-      int IdToRemove = (*it)->GetID();
-      int vtkid = (*it)->getVtkId();
-      //MESSAGE("elem Id to remove " << IdToRemove << " vtkid " << vtkid <<
-      //        " vtktype " << (*it)->GetVtkType() << " type " << (*it)->GetType());
-      switch ((*it)->GetType())
-      {
-        case SMDSAbs_Node:
-          MYASSERT("Internal Error: This should not happen")
-          ;
-          break;
-        case SMDSAbs_0DElement:
-          if (IdToRemove >= 0)
-            {
-              myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
-              myInfo.remove(*it);
-            }
-          removedElems.push_back((*it));
-          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
-          delete (*it);
-          break;
-        case SMDSAbs_Edge:
-          if (IdToRemove >= 0)
-            {
-              myCells[IdToRemove] = 0;
-              myInfo.RemoveEdge(*it);
-            }
-          removedElems.push_back((*it));
-          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
-          if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
-            myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
-          else
-            delete (*it);
-          break;
-        case SMDSAbs_Face:
-          if (IdToRemove >= 0)
-            {
-              myCells[IdToRemove] = 0;
-              myInfo.RemoveFace(*it);
-            }
-          removedElems.push_back((*it));
-          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
-          if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
-            myFacePool->destroy((SMDS_VtkFace*) vtkElem);
-          else
-            delete (*it);
-          break;
-        case SMDSAbs_Volume:
-          if (IdToRemove >= 0)
-            {
-              myCells[IdToRemove] = 0;
-              myInfo.RemoveVolume(*it);
-            }
-          removedElems.push_back((*it));
-          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
-          if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
-            myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
-          else
-            delete (*it);
-          break;
-        case SMDSAbs_Ball:
-          if (IdToRemove >= 0)
-            {
-              myCells[IdToRemove] = 0;
-              myInfo.remove(*it);
-            }
-          removedElems.push_back((*it));
-          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
-          if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
-            myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
-          else
-            delete (*it);
-          break;
-      }
-      if (vtkid >= 0)
-        {
-          //MESSAGE("VTK_EMPTY_CELL in " << vtkid);
-          this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
-        }
-      it++;
+      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;
+    }
+
+    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 )
     {
-      it = s2->begin();
-      while (it != s2->end())
-        {
-          int IdToRemove = (*it)->GetID();
-          //MESSAGE( "SMDS: RM node " << IdToRemove);
-          if (IdToRemove >= 0)
-            {
-              myNodes[IdToRemove] = 0;
-              myInfo.myNbNodes--;
-            }
-          myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
-          removedNodes.push_back((*it));
-          if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
-          {
-            ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
-            myNodePool->destroy((SMDS_MeshNode*) vtkElem);
-          }
-          else
-            delete (*it);
-          it++;
-        }
+      myInfo.myNbNodes--;
+      myNodeFactory->Free( (*it) );
+      removedNodes.push_back((*it));
     }
+  }
 
   delete s2;
   delete s1;
@@ -3392,92 +1861,60 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
 {
-  int elemId = elem->GetID();
-  int vtkId = elem->getVtkId();
-  //MESSAGE("RemoveFreeElement " << elemId);
+  const int           vtkId = elem->GetVtkID();
   SMDSAbs_ElementType aType = elem->GetType();
-  SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
-  if (aType == SMDSAbs_Node) {
-    //MESSAGE("Remove free node " << elemId);
+  if ( aType == SMDSAbs_Node )
+  {
     // only free node can be removed by this method
-    const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
-    SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
-    if (!itFe->more()) { // free node
-      myNodes[elemId] = 0;
+    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( elem );
+    if ( n->NbInverseElements() == 0 ) { // free node
       myInfo.myNbNodes--;
-      ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
-      ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
-      myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
-      myNodeIDFactory->ReleaseID(elemId, vtkId);
+      myNodeFactory->Free( n );
     }
-  } else {
-    if (hasConstructionEdges() || hasConstructionFaces())
-      // this methods is only for meshes without descendants
-      return;
-
-    //MESSAGE("Remove free element " << elemId);
+    else
+    {
+      throw SALOME_Exception( LOCALIZED( "RemoveFreeElement: not a free node" ));
+    }
+  }
+  else
+  {
     // Remove element from <InverseElements> of its nodes
-    SMDS_ElemIteratorPtr itn = elem->nodesIterator();
+    SMDS_NodeIteratorPtr itn = elem->nodeIterator();
     while (itn->more()) {
-      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
-        (const_cast<SMDS_MeshElement *>(itn->next()));
+      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:
-      myCells[elemId] = 0;
-      myInfo.remove(elem);
-      delete elem;
-      break;
-    case SMDSAbs_Edge:
-      myCells[elemId] = 0;
-      myInfo.RemoveEdge(elem);
-      myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
-      break;
-    case SMDSAbs_Face:
-      myCells[elemId] = 0;
-      myInfo.RemoveFace(elem);
-      myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
-      break;
-    case SMDSAbs_Volume:
-      myCells[elemId] = 0;
-      myInfo.RemoveVolume(elem);
-      myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
-      break;
-    case SMDSAbs_Ball:
-      myCells[elemId] = 0;
-      myInfo.remove(elem);
-      myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
-      break;
-    default:
-      break;
+    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;
     }
-    myElementIDFactory->ReleaseID(elemId, vtkId);
+    myCellFactory->Free( elem );
 
     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
-    // --- to do: keep vtkid in a list of reusable cells
   }
 }
 
+//=======================================================================
 /*!
  * Checks if the element is present in mesh.
- * Useful to determine dead pointers.
  */
+//=======================================================================
+
 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
 {
-  // we should not imply on validity of *elem, so iterate on containers
-  // of all types in the hope of finding <elem> somewhere there
-  SMDS_NodeIteratorPtr itn = nodesIterator();
-  while (itn->more())
-    if (elem == itn->next())
-      return true;
-  SMDS_ElemIteratorPtr ite = elementsIterator();
-  while (ite->more())
-    if (elem == ite->next())
-      return true;
-  return false;
+  if ( !elem || elem->IsNull() )
+    return false;
+
+  if ( elem->GetType() == SMDSAbs_Node )
+    return ( elem == myNodeFactory->FindElement( elem->GetID() ));
+
+  return ( elem == myCellFactory->FindElement( elem->GetID() ));
 }
 
 //=======================================================================
@@ -3487,7 +1924,7 @@ bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
 
 int SMDS_Mesh::MaxNodeID() const
 {
-  return myNodeMax;
+  return myNodeFactory->GetMaxID();
 }
 
 //=======================================================================
@@ -3497,7 +1934,7 @@ int SMDS_Mesh::MaxNodeID() const
 
 int SMDS_Mesh::MinNodeID() const
 {
-  return myNodeMin;
+  return myNodeFactory->GetMinID();
 }
 
 //=======================================================================
@@ -3507,7 +1944,7 @@ int SMDS_Mesh::MinNodeID() const
 
 int SMDS_Mesh::MaxElementID() const
 {
-  return myElementIDFactory->GetMaxID();
+  return myCellFactory->GetMaxID();
 }
 
 //=======================================================================
@@ -3517,7 +1954,7 @@ int SMDS_Mesh::MaxElementID() const
 
 int SMDS_Mesh::MinElementID() const
 {
-  return myElementIDFactory->GetMinID();
+  return myCellFactory->GetMinID();
 }
 
 //=======================================================================
@@ -3525,40 +1962,12 @@ int SMDS_Mesh::MinElementID() const
 //purpose  : Renumber all nodes or elements.
 //=======================================================================
 
-void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
-{
-    MESSAGE("Renumber");
-  if ( deltaID == 0 )
-    return;
-
-  SMDS_MeshNodeIDFactory * idFactory =
-    isNodes ? myNodeIDFactory : myElementIDFactory;
+// void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
+// {
+//   if ( deltaID == 0 )
+//     return;
 
-  // get existing elements in the order of ID increasing
-  map<int,SMDS_MeshElement*> elemMap;
-  SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
-  while ( idElemIt->more() ) {
-    SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
-    int id = elem->GetID();
-    elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
-  }
-  // release their ids
-  map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
-  idFactory->Clear();
-//   for ( ; elemIt != elemMap.end(); elemIt++ )
-//   {
-//     int id = (*elemIt).first;
-//     idFactory->ReleaseID( id );
-//   }
-  // set new IDs
-  int ID = startID;
-  elemIt = elemMap.begin();
-  for ( ; elemIt != elemMap.end(); elemIt++ )
-  {
-    idFactory->BindID( ID, (*elemIt).second );
-    ID += deltaID;
-  }
-}
+// }
 
 //=======================================================================
 //function : GetElementType
@@ -3567,19 +1976,13 @@ void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  del
 
 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
 {
-  SMDS_MeshElement* elem = 0;
+  const SMDS_MeshElement* elem = 0;
   if( iselem )
-    elem = myElementIDFactory->MeshElement( id );
+    elem = myCellFactory->FindElement( id );
   else
-    elem = myNodeIDFactory->MeshElement( id );
+    elem = myNodeFactory->FindElement( id );
 
-  if( !elem )
-  {
-    //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
-    return SMDSAbs_All;
-  }
-  else
-    return elem->GetType();
+  return elem ? elem->GetType() : SMDSAbs_All;
 }
 
 
@@ -3598,11 +2001,10 @@ SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem )
 //=======================================================================
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
 {
-  return SMDS_Mesh::AddEdgeWithID
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     ID);
+  return SMDS_Mesh::AddEdgeWithID (myNodeFactory->FindNode(n1),
+                                   myNodeFactory->FindNode(n2),
+                                   myNodeFactory->FindNode(n12),
+                                   ID);
 }
 
 //=======================================================================
@@ -3613,7 +2015,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
                                   const SMDS_MeshNode* n2,
                                   const SMDS_MeshNode* n12)
 {
-  return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
+  return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -3623,36 +2025,17 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n2,
                                         const SMDS_MeshNode * n12,
-                                        int ID)
+                                        int                   ID)
 {
   if ( !n1 || !n2 || !n12 ) return 0;
 
-  // --- retrieve nodes ID
-  myNodeIds.resize(3);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n2->getVtkId();
-  myNodeIds[2] = n12->getVtkId();
-
-  SMDS_MeshEdge * edge = 0;
-  SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
-  edgevtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,edgevtk))
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
-    myEdgePool->destroy(edgevtk);
-    return 0;
+    cell->init( SMDSEntity_Quad_Edge, /*nbNodes=*/3, n1, n2, n12 );
+    myInfo.myNbQuadEdges++;
+    return static_cast<SMDS_MeshEdge*>( cell );
   }
-  edge = edgevtk;
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = edge;
-  myInfo.myNbQuadEdges++;
-
-  //  if (!registerElement(ID, edge)) {
-  //        RemoveElement(edge, false);
-  //        edge = NULL;
-  //  }
-  return edge;
-
+  return 0;
 }
 
 
@@ -3668,7 +2051,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * n31)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
-                                  myElementIDFactory->GetFreeID());
+                                  myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -3678,14 +2061,13 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
                                         int n12,int n23,int n31, int ID)
 {
-  return SMDS_Mesh::AddFaceWithID
-    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
-     ID);
+  return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
+                                   myNodeFactory->FindNode(n2) ,
+                                   myNodeFactory->FindNode(n3) ,
+                                   myNodeFactory->FindNode(n12),
+                                   myNodeFactory->FindNode(n23),
+                                   myNodeFactory->FindNode(n31),
+                                   ID);
 }
 
 //=======================================================================
@@ -3700,42 +2082,16 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n31,
                                         int ID)
 {
-  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
-  if(hasConstructionEdges()) {
-    // creation quadratic edges - not implemented
-    return 0;
-  }
-  else
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    // --- retrieve nodes ID
-    myNodeIds.resize(6);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n2->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n12->getVtkId();
-    myNodeIds[4] = n23->getVtkId();
-    myNodeIds[5] = n31->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+    cell->init( SMDSEntity_Quad_Triangle, /*nbNodes=*/6, n1, n2, n3, n12, n23, n31 );
     myInfo.myNbQuadTriangles++;
-
-    //    if (!registerElement(ID, face)) {
-    //      RemoveElement(face, false);
-    //      face = NULL;
-    //    }
-    return face;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
+  return 0;
 }
 
 
@@ -3752,7 +2108,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * nCenter)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
-                                  myElementIDFactory->GetFreeID());
+                                  myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -3762,15 +2118,14 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 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
-    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
-     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);
 }
 
 //=======================================================================
@@ -3787,42 +2142,15 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         int ID)
 {
   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
-  if(hasConstructionEdges()) {
-    // creation quadratic edges - not implemented
-    return 0;
-  }
-  else
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    // --- retrieve nodes ID
-    myNodeIds.resize(7);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n2->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n12->getVtkId();
-    myNodeIds[4] = n23->getVtkId();
-    myNodeIds[5] = n31->getVtkId();
-    myNodeIds[6] = nCenter->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+    cell->init( SMDSEntity_BiQuad_Triangle, /*nbNodes=*/7, n1, n2, n3, n12, n23, n31, nCenter );
     myInfo.myNbBiQuadTriangles++;
-
-    //    if (!registerElement(ID, face)) {
-    //      RemoveElement(face, false);
-    //      face = NULL;
-    //    }
-    return face;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
+  return 0;
 }
 
 
@@ -3840,7 +2168,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * n41)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
-                                  myElementIDFactory->GetFreeID());
+                                  myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -3850,16 +2178,15 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 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
-    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
-     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);
 }
 
 //=======================================================================
@@ -3877,43 +2204,15 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         int ID)
 {
   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
-  if(hasConstructionEdges()) {
-    // creation quadratic edges - not implemented
-    return 0;
-  }
-  else
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    // --- retrieve nodes ID
-    myNodeIds.resize(8);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n2->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n4->getVtkId();
-    myNodeIds[4] = n12->getVtkId();
-    myNodeIds[5] = n23->getVtkId();
-    myNodeIds[6] = n34->getVtkId();
-    myNodeIds[7] = n41->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+    cell->init( SMDSEntity_Quad_Quadrangle, /*nbNodes=*/8, n1, n2, n3, n4, n12, n23, n34, n41 );
     myInfo.myNbQuadQuadrangles++;
-
-    //    if (!registerElement(ID, face)) {
-    //      RemoveElement(face, false);
-    //      face = NULL;
-    //    }
-    return face;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
+  return 0;
 }
 
 //=======================================================================
@@ -3931,7 +2230,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
                                   const SMDS_MeshNode * nCenter)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
-                                  myElementIDFactory->GetFreeID());
+                                  myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -3941,17 +2240,16 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 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
-    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
-     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
-     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);
 }
 
 //=======================================================================
@@ -3970,44 +2268,16 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         int ID)
 {
   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
-  if(hasConstructionEdges()) {
-    // creation quadratic edges - not implemented
-    return 0;
-  }
-  else
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    // --- retrieve nodes ID
-    myNodeIds.resize(9);
-    myNodeIds[0] = n1->getVtkId();
-    myNodeIds[1] = n2->getVtkId();
-    myNodeIds[2] = n3->getVtkId();
-    myNodeIds[3] = n4->getVtkId();
-    myNodeIds[4] = n12->getVtkId();
-    myNodeIds[5] = n23->getVtkId();
-    myNodeIds[6] = n34->getVtkId();
-    myNodeIds[7] = n41->getVtkId();
-    myNodeIds[8] = nCenter->getVtkId();
-
-    SMDS_MeshFace * face = 0;
-    SMDS_VtkFace *facevtk = myFacePool->getNew();
-    facevtk->init(myNodeIds, this);
-    if (!this->registerElement(ID,facevtk))
-    {
-      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
-      myFacePool->destroy(facevtk);
-      return 0;
-    }
-    face = facevtk;
-    adjustmyCellsCapacity(ID);
-    myCells[ID] = face;
+    cell->init( SMDSEntity_BiQuad_Quadrangle,
+                /*nbNodes=*/9, n1, n2, n3, n4, n12, n23, n34, n41, nCenter );
     myInfo.myNbBiQuadQuadrangles++;
-
-    //    if (!registerElement(ID, face)) {
-    //      RemoveElement(face, false);
-    //      face = NULL;
-    //    }
-    return face;
+    return static_cast<SMDS_MeshFace*>( cell );
   }
+  return 0;
 }
 
 
@@ -4026,11 +2296,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n24,
                                       const SMDS_MeshNode * n34)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
-                                                   n31, n14, n24, n34, ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
+                                    n31, n14, n24, n34, myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -4041,18 +2308,17 @@ 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
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
-     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);
 }
 
 //=======================================================================
@@ -4073,42 +2339,16 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 {
   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
     return 0;
-  if(hasConstructionFaces()) {
-    // creation quadratic faces - not implemented
-    return 0;
-  }
-  // --- retrieve nodes ID
-  myNodeIds.resize(10);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n3->getVtkId();
-  myNodeIds[2] = n2->getVtkId();
-  myNodeIds[3] = n4->getVtkId();
-
-  myNodeIds[4] = n31->getVtkId();
-  myNodeIds[5] = n23->getVtkId();
-  myNodeIds[6] = n12->getVtkId();
-
-  myNodeIds[7] = n14->getVtkId();
-  myNodeIds[8] = n34->getVtkId();
-  myNodeIds[9] = n24->getVtkId();
-
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-    myVolumePool->destroy(volvtk);
-    return 0;
+    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 );
   }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  myInfo.myNbQuadTetras++;
-
-  //  if (!registerElement(ID, volvtk)) {
-  //    RemoveElement(volvtk, false);
-  //    volvtk = NULL;
-  //  }
-  return volvtk;
+  return 0;
 }
 
 
@@ -4130,12 +2370,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n35,
                                       const SMDS_MeshNode * n45)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v =
-    SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
-                               n15, n25, n35, n45, ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
+                                    n15, n25, n35, n45, myCellFactory->GetFreeID());
 }
 
 //=======================================================================
@@ -4146,21 +2382,20 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int
                                             int n12,int n23,int n34,int n41,
                                             int n15,int n25,int n35,int n45, int ID)
 {
-  return SMDS_Mesh::AddVolumeWithID
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
-     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);
 }
 
 //=======================================================================
@@ -4185,51 +2420,22 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
     return 0;
-  if(hasConstructionFaces()) {
-    // creation quadratic faces - not implemented
-    return 0;
-  }
-  // --- retrieve nodes ID
-  myNodeIds.resize(13);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n4->getVtkId();
-  myNodeIds[2] = n3->getVtkId();
-  myNodeIds[3] = n2->getVtkId();
-  myNodeIds[4] = n5->getVtkId();
-
-  myNodeIds[5] = n41->getVtkId();
-  myNodeIds[6] = n34->getVtkId();
-  myNodeIds[7] = n23->getVtkId();
-  myNodeIds[8] = n12->getVtkId();
-
-  myNodeIds[9] = n15->getVtkId();
-  myNodeIds[10] = n45->getVtkId();
-  myNodeIds[11] = n35->getVtkId();
-  myNodeIds[12] = n25->getVtkId();
-
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-    myVolumePool->destroy(volvtk);
-    return 0;
+    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 );
   }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  myInfo.myNbQuadPyramids++;
-
-  //  if (!registerElement(ID, volvtk)) {
-  //    RemoveElement(volvtk, false);
-  //    volvtk = NULL;
-  //  }
-  return volvtk;
+  return 0;
 }
 
 
 //=======================================================================
 //function : AddVolume
-//purpose  :
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n2,
@@ -4247,17 +2453,13 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n25,
                                       const SMDS_MeshNode * n36)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v =
-    SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
-                               n45, n56, n64, n14, n25, n36, ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
+                                    n45, n56, n64, n14, n25, n36, myCellFactory->GetFreeID());
 }
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  :
+//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,
@@ -4265,28 +2467,27 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
                                             int n45,int n56,int n64,
                                             int n14,int n25,int n36, int ID)
 {
-  return SMDS_Mesh::AddVolumeWithID
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
-     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 with 15 nodes
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n2,
@@ -4308,49 +2509,116 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
     return 0;
-  if(hasConstructionFaces()) {
-    // creation quadratic faces - not implemented
-    return 0;
-  }
-  // --- retrieve nodes ID
-  myNodeIds.resize(15);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n2->getVtkId();
-  myNodeIds[2] = n3->getVtkId();
-
-  myNodeIds[3] = n4->getVtkId();
-  myNodeIds[4] = n5->getVtkId();
-  myNodeIds[5] = n6->getVtkId();
-
-  myNodeIds[6] = n12->getVtkId();
-  myNodeIds[7] = n23->getVtkId();
-  myNodeIds[8] = n31->getVtkId();
-
-  myNodeIds[9] = n45->getVtkId();
-  myNodeIds[10] = n56->getVtkId();
-  myNodeIds[11] = n64->getVtkId();
-
-  myNodeIds[12] = n14->getVtkId();
-  myNodeIds[13] = n25->getVtkId();
-  myNodeIds[14] = n36->getVtkId();
-
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-    myVolumePool->destroy(volvtk);
-    return 0;
+    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 );
   }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  myInfo.myNbQuadPrisms++;
+  return 0;
+}
 
-  //  if (!registerElement(ID, volvtk)) {
-  //    RemoveElement(volvtk, false);
-  //    volvtk = NULL;
-  //  }
-  return volvtk;
+//=======================================================================
+//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;
 }
 
 
@@ -4379,12 +2647,9 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n37,
                                       const SMDS_MeshNode * n48)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v =
-    SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
-                               n56, n67, n78, n85, n15, n26, n37, n48, ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  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());
 }
 
 //=======================================================================
@@ -4397,28 +2662,27 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
                                             int n56,int n67,int n78,int n85,
                                             int n15,int n26,int n37,int n48, int ID)
 {
-  return SMDS_Mesh::AddVolumeWithID
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
-     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);
 }
 
 //=======================================================================
@@ -4450,54 +2714,16 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
     return 0;
-  if(hasConstructionFaces()) {
-    return 0;
-    // creation quadratic faces - not implemented
-  }
-  // --- retrieve nodes ID
-  myNodeIds.resize(20);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n4->getVtkId();
-  myNodeIds[2] = n3->getVtkId();
-  myNodeIds[3] = n2->getVtkId();
-
-  myNodeIds[4] = n5->getVtkId();
-  myNodeIds[5] = n8->getVtkId();
-  myNodeIds[6] = n7->getVtkId();
-  myNodeIds[7] = n6->getVtkId();
-
-  myNodeIds[8] = n41->getVtkId();
-  myNodeIds[9] = n34->getVtkId();
-  myNodeIds[10] = n23->getVtkId();
-  myNodeIds[11] = n12->getVtkId();
-
-  myNodeIds[12] = n85->getVtkId();
-  myNodeIds[13] = n78->getVtkId();
-  myNodeIds[14] = n67->getVtkId();
-  myNodeIds[15] = n56->getVtkId();
-
-  myNodeIds[16] = n15->getVtkId();
-  myNodeIds[17] = n48->getVtkId();
-  myNodeIds[18] = n37->getVtkId();
-  myNodeIds[19] = n26->getVtkId();
-
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-    myVolumePool->destroy(volvtk);
-    return 0;
+    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 );
   }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  myInfo.myNbQuadHexas++;
-
-  //  if (!registerElement(ID, volvtk)) {
-  //    RemoveElement(volvtk, false);
-  //    volvtk = NULL;
-  //  }
-  return volvtk;
+  return 0;
 }
 
 //=======================================================================
@@ -4532,14 +2758,10 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n5678,
                                       const SMDS_MeshNode * nCenter)
 {
-  int ID = myElementIDFactory->GetFreeID();
-  SMDS_MeshVolume * v =
-    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,
-                               ID);
-  if(v==NULL) myElementIDFactory->ReleaseID(ID);
-  return v;
+  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());
 }
 
 //=======================================================================
@@ -4554,40 +2776,39 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
                                             int n1234,int n1256,int n2367,int n3478,
                                             int n1458,int n5678,int nCenter, int ID)
 {
-  return SMDS_Mesh::AddVolumeWithID
-    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
-     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
-     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 20 nodes
+//purpose  : 2d order Hexahedrons with 27 nodes
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n2,
@@ -4622,185 +2843,116 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
     return 0;
-  if(hasConstructionFaces()) {
-    return 0;
-    // creation quadratic faces - not implemented
-  }
-  // --- retrieve nodes ID
-  myNodeIds.resize(27);
-  myNodeIds[0] = n1->getVtkId();
-  myNodeIds[1] = n4->getVtkId();
-  myNodeIds[2] = n3->getVtkId();
-  myNodeIds[3] = n2->getVtkId();
-
-  myNodeIds[4] = n5->getVtkId();
-  myNodeIds[5] = n8->getVtkId();
-  myNodeIds[6] = n7->getVtkId();
-  myNodeIds[7] = n6->getVtkId();
-
-  myNodeIds[8] = n41->getVtkId();
-  myNodeIds[9] = n34->getVtkId();
-  myNodeIds[10] = n23->getVtkId();
-  myNodeIds[11] = n12->getVtkId();
-
-  myNodeIds[12] = n85->getVtkId();
-  myNodeIds[13] = n78->getVtkId();
-  myNodeIds[14] = n67->getVtkId();
-  myNodeIds[15] = n56->getVtkId();
-
-  myNodeIds[16] = n15->getVtkId();
-  myNodeIds[17] = n48->getVtkId();
-  myNodeIds[18] = n37->getVtkId();
-  myNodeIds[19] = n26->getVtkId();
-
-  myNodeIds[20] = n1256->getVtkId();
-  myNodeIds[21] = n3478->getVtkId();
-  myNodeIds[22] = n1458->getVtkId();
-  myNodeIds[23] = n2367->getVtkId();
-  myNodeIds[24] = n1234->getVtkId();
-  myNodeIds[25] = n5678->getVtkId();
-  myNodeIds[26] = nCenter->getVtkId();
-
-  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
-  volvtk->init(myNodeIds, this);
-  if (!this->registerElement(ID,volvtk))
-  {
-    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
-    myVolumePool->destroy(volvtk);
-    return 0;
-  }
-  adjustmyCellsCapacity(ID);
-  myCells[ID] = volvtk;
-  myInfo.myNbTriQuadHexas++;
-
-  return volvtk;
-}
-
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-void SMDS_Mesh::updateNodeMinMax()
-{
-  myNodeMin = 0;
-  if (myNodes.size() == 0)
+  if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
   {
-    myNodeMax=0;
-    return;
+    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 );
   }
-  while (!myNodes[myNodeMin] && (myNodeMin<myNodes.size()))
-    myNodeMin++;
-  myNodeMax=myNodes.size()-1;
-  while (!myNodes[myNodeMax] && (myNodeMin>=0))
-    myNodeMin--;
-}
-
-void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
-{
-//  int val = myCellIdSmdsToVtk.size();
-//  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
-//  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
-  int val = myNodes.size();
-  MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes);
-  myNodes.resize(val +nbNodes, 0);
-}
-
-void SMDS_Mesh::incrementCellsCapacity(int nbCells)
-{
-  int val = myCellIdVtkToSmds.size();
-  MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells);
-  myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
-  val = myCells.size();
-  MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells);
-  myNodes.resize(val +nbCells, 0);
-}
-
-void SMDS_Mesh::adjustStructure()
-{
-  myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
+  return 0;
 }
 
-void SMDS_Mesh::dumpGrid(string ficdump)
+void SMDS_Mesh::dumpGrid(std::string ficdump)
 {
-        MESSAGE("SMDS_Mesh::dumpGrid " << ficdump);
-//  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
-//  aWriter->SetFileName(ficdump.c_str());
-//  aWriter->SetInput(myGrid);
-//  if(myGrid->GetNumberOfCells())
-//  {
-//    aWriter->Write();
-//  }
-//  aWriter->Delete();
+  //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
+  //  aWriter->SetFileName(ficdump.c_str());
+  //  aWriter->SetInput(myGrid);
+  //  if(myGrid->GetNumberOfCells())
+  //  {
+  //    aWriter->Write();
+  //  }
+  //  aWriter->Delete();
   ficdump = ficdump + "_connectivity";
-  ofstream ficcon(ficdump.c_str(), ios::out);
+  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;
+    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++)
   {
-//      MESSAGE(i << " " << myGrid->GetCell(i));
-//      MESSAGE("  " << myGrid->GetCell(i)->GetCellType());
-        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 << 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->GetCellLinks();
+  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;
+    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()
+void SMDS_Mesh::CompactMesh()
 {
-  MESSAGE("SMDS_Mesh::compactMesh do nothing!");
-}
+  this->myCompactTime = this->myModifTime;
 
-int SMDS_Mesh::fromVtkToSmds(int vtkid)
-{
-  if (vtkid >= 0 && vtkid < myCellIdVtkToSmds.size())
-    return myCellIdVtkToSmds[vtkid];
-  throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
-}
+  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();
 
-void SMDS_Mesh::updateBoundingBox()
-{
-  xmin = 0; xmax = 0;
-  ymin = 0; ymax = 0;
-  zmin = 0; zmax = 0;
-  vtkPoints *points = myGrid->GetPoints();
-  int myNodesSize = this->myNodes.size();
-  for (int i = 0; i < myNodesSize; i++)
+  // 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 (SMDS_MeshNode *n = myNodes[i])
-        {
-          double coords[3];
-          points->GetPoint(n->myVtkID, coords);
-          if (coords[0] < xmin) xmin = coords[0];
-          else if (coords[0] > xmax) xmax = coords[0];
-          if (coords[1] < ymin) ymin = coords[1];
-          else if (coords[1] > ymax) ymax = coords[1];
-          if (coords[2] < zmin) zmin = coords[2];
-          else if (coords[2] > zmax) zmax = coords[2];
-        }
+      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()
@@ -4809,7 +2961,6 @@ double SMDS_Mesh::getMaxDim()
   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
-  MESSAGE("getMaxDim " << dmax);
   return dmax;
 }
 
@@ -4817,26 +2968,24 @@ double SMDS_Mesh::getMaxDim()
 void SMDS_Mesh::Modified()
 {
   if (this->myModified)
-    {
-      this->myModifTime++;
-      MESSAGE("modified");
-      myModified = false;
-    }
+  {
+    this->myModifTime++;
+    myModified = false;
+  }
 }
 
 //! get last modification timeStamp
-unsigned long SMDS_Mesh::GetMTime() const
+vtkMTimeType SMDS_Mesh::GetMTime() const
 {
   return this->myModifTime;
 }
 
-bool SMDS_Mesh::isCompacted()
+bool SMDS_Mesh::IsCompacted()
 {
-  if (this->myModifTime > this->myCompactTime)
-    {
-      MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime);
-      this->myCompactTime = this->myModifTime;
-      return false;
-    }
-  return true;
+  return ( this->myCompactTime == this->myModifTime );
+}
+
+void SMDS_Mesh::setNbShapes( size_t nbShapes )
+{
+  myNodeFactory->SetNbShapes( nbShapes );
 }