Salome HOME
Update copyright info (2010->2011)
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 9ba95601271f0c9545a1bf170ee1eefdf1719c24..aa96e661d2486fb064264bd99c3ef55f92399bae 100644 (file)
-//  SMESH SMDS : implementaion of Salome mesh data structure
+//  Copyright (C) 2007-2011  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
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : SMDS_Mesh.cxx
-//  Author : Jean-Michel BOULCOURT
-//  Module : SMESH
 
-using namespace std;
-#include "SMDS_Mesh.ixx"
-#include "SMDS_MapIteratorOfExtendedOrientedMap.hxx"
-#include "SMDS_ListOfMeshElement.hxx"
-#include "SMDS_ListIteratorOfListOfMeshElement.hxx"
-#include "SMDS_MeshNode.hxx"
-#include "SMDS_MeshEdge.hxx"
-#include "SMDS_MeshFace.hxx"
-#include "SMDS_MeshTriangle.hxx"
-#include "SMDS_MeshQuadrangle.hxx"
-#include "SMDS_MeshVolume.hxx"
-#include "SMDS_MeshTetrahedron.hxx"
-#include "SMDS_MeshPyramid.hxx"
-#include "SMDS_MeshPrism.hxx"
-#include "SMDS_MeshHexahedron.hxx"
-#include "SMDS_ListOfMesh.hxx"
-#include "SMDS_ListIteratorOfListOfMesh.hxx"
-
-
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_NoSuchObject.hxx>
+//  SMESH SMDS : implementaion of Salome mesh data structure
+//
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
 
 #include "utilities.h"
+#include "SMDS_Mesh.hxx"
+#include "SMDS_VolumeOfNodes.hxx"
+#include "SMDS_VolumeOfFaces.hxx"
+#include "SMDS_FaceOfNodes.hxx"
+#include "SMDS_FaceOfEdges.hxx"
+#include "SMDS_PolyhedralVolumeOfNodes.hxx"
+#include "SMDS_PolygonalFaceOfNodes.hxx"
+#include "SMDS_QuadraticEdge.hxx"
+#include "SMDS_QuadraticFaceOfNodes.hxx"
+#include "SMDS_QuadraticVolumeOfNodes.hxx"
+
+#include <algorithm>
+#include <map>
+using namespace std;
 
+#ifndef WIN32
+#include <sys/sysinfo.h>
+#endif
+
+// number of added entitis to check memory after
+#define CHECKMEMORY_INTERVAL 1000
+
+//================================================================================
+/*!
+ * \brief Raise an exception if free memory (ram+swap) too low
+ * \param doNotRaise - if true, suppres exception, just return free memory size
+ * \retval int - amount of available memory in MB or negative number in failure case
+ */
+//================================================================================
+
+int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
+{
+#ifndef WIN32
+  struct sysinfo si;
+  int err = sysinfo( &si );
+  if ( err )
+    return -1;
+
+  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);
+    }
+    if ( limit < 20 )
+      limit = 20;
+    else
+      limit = int( limit * 1.5 );
+#ifdef _DEBUG_
+    MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
+#endif
+  }
 
-//=======================================================================
-//function : SMDS_Mesh
-//purpose  : creation of a new mesh object
-//=======================================================================
+  const unsigned long Mbyte = 1024 * 1024;
+  // compute separately to avoid overflow
+  int freeMb =
+    ( si.freeram  * si.mem_unit ) / Mbyte +
+    ( si.freeswap * si.mem_unit ) / Mbyte;
+
+  if ( freeMb > limit )
+    return freeMb - limit;
+
+  if ( doNotRaise )
+    return 0;
+#ifdef _DEBUG_
+  MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
+#endif
+  throw std::bad_alloc();
+#else
+  return -1;
+#endif
+}
 
-SMDS_Mesh::SMDS_Mesh(const Standard_Integer nbnodes,
-                    const Standard_Integer nbedges, 
-                    const Standard_Integer nbfaces,
-                    const Standard_Integer nbvolumes)
-  :myNodes(nbnodes),myEdges(nbedges),myFaces(nbfaces),myVolumes(nbvolumes),
-   myNodeIDFactory(new SMDS_MeshNodeIDFactory()), 
-   myElementIDFactory(new SMDS_MeshElementIDFactory()),myHasInverse(Standard_False)
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new mesh object
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh::SMDS_Mesh()
+        :myParent(NULL),
+        myNodeIDFactory(new SMDS_MeshElementIDFactory()),
+        myElementIDFactory(new SMDS_MeshElementIDFactory()),
+        myHasConstructionEdges(false), myHasConstructionFaces(false),
+        myHasInverseElements(true)
 {
 }
 
-//=======================================================================
-//function : SMDS_Mesh
-//purpose  :  
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new child 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)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a submesh and add it to the current mesh
+///////////////////////////////////////////////////////////////////////////////
 
-SMDS_Mesh::SMDS_Mesh(const Handle(SMDS_Mesh)& parent,
-                    const Standard_Integer nbnodes)
-  :myNodes(nbnodes),myParent(parent),myNodeIDFactory(parent->myNodeIDFactory),
-   myElementIDFactory(parent->myElementIDFactory),
-   myHasInverse(Standard_False)
+SMDS_Mesh *SMDS_Mesh::AddSubMesh()
 {
+        SMDS_Mesh *submesh = new SMDS_Mesh(this);
+        myChildren.insert(myChildren.end(), submesh);
+        return submesh;
 }
 
-//=======================================================================
-//function : AddSubMesh
-//purpose  : create an submesh
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+///create a MeshNode and add it to the current Mesh
+///An ID is automatically assigned to the node.
+///@return : The created node
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_Mesh) SMDS_Mesh::AddSubMesh()
+SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
 {
-  Handle(SMDS_Mesh) submesh = new SMDS_Mesh(this);
-  if (!submesh.IsNull()) {
-    myChildren.Append(submesh);
-  }
+  return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
+}
 
-  return submesh;
+///////////////////////////////////////////////////////////////////////////////
+///create a MeshNode and add it to the current Mesh
+///@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)
+{
+  // find the MeshNode corresponding to ID
+  const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
+  if(!node){
+    if ( myNodes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+    SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
+    myNodes.Add(node);
+    myNodeIDFactory->BindID(ID,node);
+    myInfo.myNbNodes++;
+    return node;
+  }else
+    return NULL;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
+{
+  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  if (!node) return NULL;
+  return SMDS_Mesh::Add0DElementWithID(node, ID);
+}
 
-//=======================================================================
-//function : AddNode
-//purpose  : create a MeshNode and returns an ID
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
+{
+  return SMDS_Mesh::Add0DElementWithID(node, myElementIDFactory->GetFreeID());
+}
 
-Standard_Integer SMDS_Mesh::AddNode(const Standard_Real x, 
-                                   const Standard_Real y, 
-                                   const Standard_Real z)
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Mesh0DElement and at it to the mesh
+/// @param idnode ID of the node
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
 {
-  Standard_Integer ID = myNodeIDFactory->GetFreeID();
+  if (!n) return 0;
 
-  Handle(SMDS_MeshElement) node = new SMDS_MeshNode(ID,x,y,z);
-  AddNode(node);
+  if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+  SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
+  if (myElementIDFactory->BindID(ID, el0d)) {
+    SMDS_MeshNode *node = const_cast<SMDS_MeshNode*>(n);
+    node->AddInverseElement(el0d);
+    my0DElements.Add(el0d);
+    myInfo.myNb0DElements++;
+    return el0d;
+  }
 
-  return ID;
+  delete el0d;
+  return NULL;
 }
 
-//=======================================================================
-//function : AddNode
-//purpose  : create a MeshNode. Returns False if the ID already exists
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// create a MeshEdge and add it to the current Mesh
+/// @return : The created MeshEdge
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Boolean SMDS_Mesh::AddNodeWithID(const Standard_Real x, 
-                                         const Standard_Real y, 
-                                         const Standard_Real z,
-                                         const Standard_Integer ID)
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 {
+  SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
+  SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
+  if(!node1 || !node2) return NULL;
+  return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
+}
 
-  // find the MeshNode corresponding to ID
-  Handle(SMDS_MeshElement) node;
-  node = GetNode(ID);
+///////////////////////////////////////////////////////////////////////////////
+/// create a MeshEdge and add it to the current Mesh
+/// @return : The created MeshEdge
+///////////////////////////////////////////////////////////////////////////////
 
-  if (node.IsNull()) {
-    node = new SMDS_MeshNode(ID,x,y,z);
-    AddNode(node);
-    return Standard_True;
-  } else
-    return Standard_False;
-    
+SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
+                                  const SMDS_MeshNode * node2)
+{
+  return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
 }
 
-//=======================================================================
-//function : AddNode
-//purpose  : add  an existing node in  the mesh (useful for submesh)
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new edge and at it to the mesh
+/// @param idnode1 ID of the first node
+/// @param idnode2 ID of the second node
+/// @param ID ID of the edge to create
+/// @return The created edge or NULL if an element with this ID already exists or
+/// if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Boolean SMDS_Mesh::AddNode(const Standard_Integer ID)
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        int ID)
 {
-  // find the MeshNode corresponding to ID
-  Handle(SMDS_MeshElement) node;
+  if ( !n1 || !n2 ) return 0;
 
-  node = GetNode(ID);
+  if ( myEdges.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-  if (!node.IsNull()) {
-    myNodes.Add(node);
-    return Standard_True;;
-  } else
-    return Standard_False;
+  SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2);
+  if(myElementIDFactory->BindID(ID, edge)) {
+    SMDS_MeshNode *node1,*node2;
+    node1=const_cast<SMDS_MeshNode*>(n1);
+    node2=const_cast<SMDS_MeshNode*>(n2);
+    node1->AddInverseElement(edge);
+    node2->AddInverseElement(edge);
+    myEdges.Add(edge);
+    myInfo.myNbEdges++;
+    return edge;
+  }
+  else {
+    delete edge;
+    return NULL;
+  }
 }
 
-//=======================================================================
-//function : AddNode
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes. An ID is automatically affected to the
+/// Created face
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Boolean SMDS_Mesh::AddNode(const Handle(SMDS_MeshElement)& node)
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3)
 {
-
-  if (!node.IsNull()) {
-    myNodes.Add(node);
-    if (!myParent.IsNull()) {
-      myParent->AddNode(node);
-    }
-    return Standard_True;
-  } else
-    return Standard_False;
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-//function : AddEdge
-//purpose  : 
-//=======================================================================
-
-Standard_Integer SMDS_Mesh::AddEdge(const Standard_Integer idnode1,
-                                           const Standard_Integer idnode2)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
 {
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddEdgeWithID(idnode1,idnode2,ID))
-    return ID;
-  else 
-    return 0;
-
+  SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
+  SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
+  SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
+  if(!node1 || !node2 || !node3) return NULL;
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
 }
 
-//=======================================================================
-//function : AddEdge
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Boolean SMDS_Mesh::AddEdgeWithID(const Standard_Integer idnode1,
-                                         const Standard_Integer idnode2,
-                                         const Standard_Integer ID)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        int ID)
 {
-  Handle(SMDS_MeshElement) edge,elem;
-  Standard_Boolean successAdd = Standard_False;
+  SMDS_MeshFace * face=createTriangle(n1, n2, n3);
 
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      elem = CreateEdge(ID,idnode1,idnode2);
-      edge = FindEdge(elem);
-      if (edge.IsNull()) {
-       edge = elem;
-       myEdges.Add(edge);
-      }
-      successAdd = myElementIDFactory->BindID(ID,edge);
-    }
+  if (face && !registerElement(ID, face)) {
+    RemoveElement(face, false);
+    face = NULL;
   }
-  
-  return successAdd;
-
+  return face;
 }
 
-//=======================================================================
-//function : AddFace
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes. An ID is automatically affected to the
+/// created face
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Integer SMDS_Mesh::AddFace(const Standard_Integer idnode1, 
-                                   const Standard_Integer idnode2,
-                                   const Standard_Integer idnode3)
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4)
 {
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddFaceWithID(idnode1,idnode2,idnode3,ID))
-    return ID;
-  else 
-    return 0;
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
 
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
+                                        int idnode2,
+                                        int idnode3,
+                                        int idnode4,
+                                        int ID)
+{
+  SMDS_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;
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
 }
 
-//=======================================================================
-//function : AddFace
-//purpose  : 
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddFaceWithID(const Standard_Integer idnode1, 
-                                         const Standard_Integer idnode2,
-                                         const Standard_Integer idnode3,
-                                         const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) face,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       elem = CreateFace(ID,idnode1,idnode2,idnode3);
-       face = FindFace(elem);
-       if (face.IsNull()) {
-         face = elem;
-         myFaces.Add(face);
-       }
-       successAdd = myElementIDFactory->BindID(ID,face);
-      }
-    }
-  }
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
 
-  return successAdd;
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        int ID)
+{
+  SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4);
 
+  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
+///////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-//function : AddFace
-//purpose  : 
-//=======================================================================
-
-Standard_Integer SMDS_Mesh::AddFace(const Standard_Integer idnode1, 
-                                           const Standard_Integer idnode2,
-                                           const Standard_Integer idnode3,
-                                           const Standard_Integer idnode4)
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
+                                  const SMDS_MeshEdge * e2,
+                                  const SMDS_MeshEdge * e3)
 {
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddFaceWithID(idnode1,idnode2,idnode3,idnode4,ID))
-    return ID;
-  else
-    return 0;
-
+  if (!hasConstructionEdges())
+    return NULL;
+  return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Add a triangle defined by its edges
+///////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-//function : AddFace
-//purpose  : 
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddFaceWithID(const Standard_Integer idnode1, 
-                                         const Standard_Integer idnode2,
-                                         const Standard_Integer idnode3,
-                                         const Standard_Integer idnode4,
-                                         const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) face,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       // find the MeshNode corresponding to idnode4
-       if (AddNode(idnode4)) {
-         elem = CreateFace(ID,idnode1,idnode2,idnode3,idnode4);
-         face = FindFace(elem);
-         if (face.IsNull()) {
-           face = elem;
-           myFaces.Add(face);
-         }
-         successAdd = myElementIDFactory->BindID(ID,face);
-       }
-      }
-    }
-  }
+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 ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
 
-  return successAdd;
+  SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
+  myFaces.Add(face);
+  myInfo.myNbTriangles++;
 
+  if (!registerElement(ID, 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;
+  return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
+}
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Tetrahedra
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadrangle defined by its edges
+///////////////////////////////////////////////////////////////////////////////
 
-Standard_Integer SMDS_Mesh::AddVolume(const Standard_Integer idnode1, 
-                                     const Standard_Integer idnode2,
-                                     const Standard_Integer idnode3,
-                                     const Standard_Integer idnode4)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
+                                        const SMDS_MeshEdge * e2,
+                                        const SMDS_MeshEdge * e3,
+                                        const SMDS_MeshEdge * e4,
+                                        int ID)
 {
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddVolumeWithID(idnode1,idnode2,idnode3,idnode4,ID))
-    return ID;
-  else
-    return 0;
+  if (!hasConstructionEdges())
+    return NULL;
+  if ( !e1 || !e2 || !e3 || !e4 ) return 0;
+  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
+  myFaces.Add(face);
+  myInfo.myNbQuadrangles++;
 
+  if (!registerElement(ID, face))
+  {
+    RemoveElement(face, false);
+    face = NULL;
+  }
+  return face;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Tetrahedra
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddVolumeWithID(const Standard_Integer idnode1, 
-                                           const Standard_Integer idnode2,
-                                           const Standard_Integer idnode3,
-                                           const Standard_Integer idnode4,
-                                           const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) volume,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       // find the MeshNode corresponding to idnode4
-       if (AddNode(idnode4)) {
-         elem = CreateVolume(ID,idnode1,idnode2,idnode3,idnode4);
-         volume = FindVolume(elem);
-         if (volume.IsNull()) {
-           volume = elem;
-           myVolumes.Add(volume);
-         }
-         successAdd = myElementIDFactory->BindID(ID,volume);
-       }
-      }
-    }
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@return The created tetrahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created tetrahedron or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int ID)
+{
+  SMDS_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;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new tetrahedron and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created tetrahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4) return volume;
+  if ( myVolumes.Extent() % 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);
+    myVolumes.Add(volume);
+    myInfo.myNbTetras++;
+  }
+  else if(hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else {
+    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4);
+    myVolumes.Add(volume);
+    myInfo.myNbTetras++;
   }
 
-  return successAdd;
-
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Pyramid
-//=======================================================================
-
-Standard_Integer SMDS_Mesh::AddVolume(const Standard_Integer idnode1, 
-                                     const Standard_Integer idnode2,
-                                     const Standard_Integer idnode3,
-                                     const Standard_Integer idnode4,
-                                     const Standard_Integer idnode5)
-{
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddVolumeWithID(idnode1,idnode2,idnode3,idnode4,idnode5,ID))
-    return ID;
-  else
-    return 0;
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@return The created pyramid
+///////////////////////////////////////////////////////////////////////////////
+
+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)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@param ID The ID of the new volume
+///@return The created pyramid or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int ID)
+{
+  SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
+  node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
+  node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
+  node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
+  node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
+  node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
+  if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new pyramid and add it to the mesh.
+///Nodes 1,2,3 and 4 define the base of the pyramid
+///@param ID The ID of the new volume
+///@return The created pyramid
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
+  if ( myVolumes.Extent() % 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);
+    myVolumes.Add(volume);
+    myInfo.myNbPyramids++;
+  }
+  else if(hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else {
+    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5);
+    myVolumes.Add(volume);
+    myInfo.myNbPyramids++;
+  }
 
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Pyramid
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddVolumeWithID(const Standard_Integer idnode1, 
-                                                   const Standard_Integer idnode2,
-                                                   const Standard_Integer idnode3,
-                                                   const Standard_Integer idnode4,
-                                                   const Standard_Integer idnode5,
-                                                   const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) volume,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       // find the MeshNode corresponding to idnode4
-       if (AddNode(idnode4)) {
-         // find the MeshNode corresponding to idnode5
-         if (AddNode(idnode5)) {
-           elem = CreateVolume(ID,idnode1,idnode2,idnode3,idnode4,idnode5);
-           volume = FindVolume(elem);
-           if (volume.IsNull()) {
-             volume = elem;
-             myVolumes.Add(volume);
-           }
-           successAdd = myElementIDFactory->BindID(ID,volume);
-         }
-       }
-      }
-    }
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+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)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int ID)
+{
+  SMDS_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;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new prism and add it to the mesh.
+///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
+  if ( myVolumes.Extent() % 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);
+    myVolumes.Add(volume);
+    myInfo.myNbPrisms++;
+  }
+  else if(hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else {
+    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6);
+    myVolumes.Add(volume);
+    myInfo.myNbPrisms++;
   }
 
-  return successAdd;
-
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Prism
-//=======================================================================
-
-Standard_Integer SMDS_Mesh::AddVolume(const Standard_Integer idnode1, 
-                                     const Standard_Integer idnode2,
-                                     const Standard_Integer idnode3,
-                                     const Standard_Integer idnode4,
-                                     const Standard_Integer idnode5,
-                                     const Standard_Integer idnode6)
-{
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddVolumeWithID(idnode1,idnode2,idnode3,idnode4,
-                     idnode5,idnode6,ID))
-    return ID;
-  else
-    return 0;
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@return The created hexahedron
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8)
+{
+  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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@param ID The ID of the new volume
+///@return The created hexahedron or NULL if an element with this ID already
+///exists or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int ID)
+{
+  SMDS_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;
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+                                    node7, node8, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexahedron and add it to the mesh.
+///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n7,
+                                            const SMDS_MeshNode * n8,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
+  if ( myVolumes.Extent() % 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);
+    myVolumes.Add(volume);
+    myInfo.myNbHexas++;
+  }
+  else if(hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else {
+//    volume=new SMDS_HexahedronOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
+    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
+    myVolumes.Add(volume);
+    myInfo.myNbHexas++;
+  }
 
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Prism
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddVolumeWithID(const Standard_Integer idnode1, 
-                                           const Standard_Integer idnode2,
-                                           const Standard_Integer idnode3,
-                                           const Standard_Integer idnode4,
-                                           const Standard_Integer idnode5,
-                                           const Standard_Integer idnode6,
-                                           const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) volume,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       // find the MeshNode corresponding to idnode4
-       if (AddNode(idnode4)) {
-         // find the MeshNode corresponding to idnode5
-         if (AddNode(idnode5)) {
-           // find the MeshNode corresponding to idnode6
-           if (AddNode(idnode6)) {
-             elem = CreateVolume(ID,idnode1,idnode2,idnode3,idnode4,idnode5,idnode6);
-             volume = FindVolume(elem);
-             if (volume.IsNull()) {
-               volume = elem;
-               myVolumes.Add(volume);
-             }
-             successAdd = myElementIDFactory->BindID(ID,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)
+{
+  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)
+{
+  if (!hasConstructionFaces())
+    return NULL;
+  if ( !f1 || !f2 || !f3 || !f4) return 0;
+  if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
+  myVolumes.Add(volume);
+  myInfo.myNbTetras++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
   }
+  return volume;
+}
 
-  return successAdd;
+///////////////////////////////////////////////////////////////////////////////
+///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)
+{
+  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)
+{
+  if (!hasConstructionFaces())
+    return NULL;
+  if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
+  if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
+  myVolumes.Add(volume);
+  myInfo.myNbPyramids++;
+
+  if (!registerElement(ID, 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)
+{
+  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)
+{
+  if (!hasConstructionFaces())
+    return NULL;
+  if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
+  if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
+  myVolumes.Add(volume);
+  myInfo.myNbPrisms++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Hexahedra
-//=======================================================================
-
-Standard_Integer SMDS_Mesh::AddVolume(const Standard_Integer idnode1, 
-                                     const Standard_Integer idnode2,
-                                     const Standard_Integer idnode3,
-                                     const Standard_Integer idnode4,
-                                     const Standard_Integer idnode5,
-                                     const Standard_Integer idnode6,
-                                     const Standard_Integer idnode7,
-                                     const Standard_Integer idnode8)
-{
-  Standard_Integer ID = myElementIDFactory->GetFreeID();
-  
-  if (AddVolumeWithID(idnode1,idnode2,idnode3,idnode4,
-                     idnode5,idnode6,idnode7,idnode8,ID))
-    return ID;
-  else
-    return 0;
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
 
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (vector<int> nodes_ids,
+                                                  const int        ID)
+{
+  int nbNodes = nodes_ids.size();
+  vector<const SMDS_MeshNode*> nodes (nbNodes);
+  for (int i = 0; i < nbNodes; i++) {
+    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
 }
 
-//=======================================================================
-//function : AddVolume
-//purpose  : Hexahedra
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::AddVolumeWithID(const Standard_Integer idnode1, 
-                                           const Standard_Integer idnode2,
-                                           const Standard_Integer idnode3,
-                                           const Standard_Integer idnode4,
-                                           const Standard_Integer idnode5,
-                                           const Standard_Integer idnode6,
-                                           const Standard_Integer idnode7,
-                                           const Standard_Integer idnode8,
-                                           const Standard_Integer ID)
-{
-  Handle(SMDS_MeshElement) volume,elem;
-  Standard_Boolean successAdd = Standard_False;
-
-  // find the MeshNode corresponding to idnode1
-  if (AddNode(idnode1)) {
-    // find the MeshNode corresponding to idnode2
-    if (AddNode(idnode2)) {
-      // find the MeshNode corresponding to idnode3
-      if (AddNode(idnode3)) {
-       // find the MeshNode corresponding to idnode4
-       if (AddNode(idnode4)) {
-         // find the MeshNode corresponding to idnode5
-         if (AddNode(idnode5)) {
-           // find the MeshNode corresponding to idnode6
-           if (AddNode(idnode6)) {
-             // find the MeshNode corresponding to idnode7
-             if (AddNode(idnode7)) {
-               // find the MeshNode corresponding to idnode8
-               if (AddNode(idnode8)) {
-                 elem = CreateVolume(ID,idnode1,idnode2,idnode3,idnode4,idnode5,
-                                     idnode6,idnode7,idnode8);
-                 volume = FindVolume(elem);
-                 if (volume.IsNull()) {
-                   volume = elem;
-                   myVolumes.Add(volume);
-                 }
-                 successAdd = myElementIDFactory->BindID(ID,volume);
-               }
-             }
-           }
-         }
-       }
-      }
-    }
-  }
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
 
-  return successAdd;
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
+                          (vector<const SMDS_MeshNode*> nodes,
+                           const int                         ID)
+{
+  SMDS_MeshFace * face;
 
-}
+  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if (hasConstructionEdges())
+  {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else
+  {
+    for ( int i = 0; i < nodes.size(); ++i )
+      if ( !nodes[ i ] ) return 0;
+    face = new SMDS_PolygonalFaceOfNodes(nodes);
+    myFaces.Add(face);
+    myInfo.myNbPolygons++;
+  }
 
+  if (!registerElement(ID, face)) {
+    RemoveElement(face, false);
+    face = NULL;
+  }
+  return face;
+}
 
-//=======================================================================
-//function : GetNode
-//purpose  : returns the MeshNode corresponding to the ID
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Add a polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_MeshElement) SMDS_Mesh::GetNode(const Standard_Integer idnode) const
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (vector<const SMDS_MeshNode*> nodes)
 {
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
+}
 
-  Handle(SMDS_MeshElement) node;
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created volume or NULL if an element with this ID already exists
+/// or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
 
-  Handle(SMDS_MeshElement) elem = FindNode(idnode);
-  if (!elem.IsNull()) { // found one correspondance
-    node =  elem;
+SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
+                             (vector<int> nodes_ids,
+                              vector<int> quantities,
+                              const int        ID)
+{
+  int nbNodes = nodes_ids.size();
+  vector<const SMDS_MeshNode*> nodes (nbNodes);
+  for (int i = 0; i < nbNodes; i++) {
+    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @param ID The ID of the new volume
+/// @return The created  volume
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
+                            (vector<const SMDS_MeshNode*> nodes,
+                             vector<int>                  quantities,
+                             const int                         ID)
+{
+  SMDS_MeshVolume* volume;
+  if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if (hasConstructionFaces()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  } else if (hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
   } else {
-    if (!myParent.IsNull())
-      node = myParent->GetNode(idnode);
+    for ( int i = 0; i < nodes.size(); ++i )
+      if ( !nodes[ i ] ) return 0;
+    volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
+    myVolumes.Add(volume);
+    myInfo.myNbPolyhedrons++;
   }
 
-  return node;
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
-//=======================================================================
-//function : FindNode
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
+/// @return The created  volume
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindNode(const Standard_Integer ID) const
+SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
+                            (vector<const SMDS_MeshNode*> nodes,
+                             vector<int>                  quantities)
 {
-  Handle(SMDS_MeshElement) elem;
-  if (myNodes.ContainsID(ID))
-    elem = myNodes.FindID(ID);
-  return elem;
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
+  if (v == NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
 }
 
-//=======================================================================
-//function : FindNode
-//purpose  : 
-//=======================================================================
-
-Handle(SMDS_MeshElement) SMDS_Mesh::FindNode(const Handle(SMDS_MeshElement)& node) const
+///////////////////////////////////////////////////////////////////////////////
+/// Registers element with the given ID, maintains inverse connections
+///////////////////////////////////////////////////////////////////////////////
+bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement * element)
 {
-  Handle(SMDS_MeshElement) elem;
-  if (myNodes.Contains(node))
-    elem = myNodes.Find(node);
+  if (myElementIDFactory->BindID(ID, element)) {
+    SMDS_ElemIteratorPtr it = element->nodesIterator();
+    while (it->more()) {
+      SMDS_MeshNode *node = static_cast<SMDS_MeshNode*>
+        (const_cast<SMDS_MeshElement*>(it->next()));
+      node->AddInverseElement(element);
+    }
+    return true;
+  }
+  return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose ID is 'ID'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
+{
+  return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a triangle and add it to the current mesh. This methode do not bind a
+///ID to the create triangle.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
+                                          const SMDS_MeshNode * node2,
+                                          const SMDS_MeshNode * node3)
+{
+  if ( !node1 || !node2 || !node3) return 0;
+  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionEdges())
+  {
+    SMDS_MeshEdge *edge1, *edge2, *edge3;
+    edge1=FindEdgeOrCreate(node1,node2);
+    edge2=FindEdgeOrCreate(node2,node3);
+    edge3=FindEdgeOrCreate(node3,node1);
+
+    SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
+    myFaces.Add(face);
+    myInfo.myNbTriangles++;
+    return face;
+  }
+  else
+  {
+    SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
+    myFaces.Add(face);
+    myInfo.myNbTriangles++;
+    return face;
+  }
+}
 
-  return elem;
+///////////////////////////////////////////////////////////////////////////////
+///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)
+{
+  if ( !node1 || !node2 || !node3 || !node4 ) return 0;
+  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionEdges())
+  {
+    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);
+    myFaces.Add(face);
+    myInfo.myNbQuadrangles++;
+    return face;
+  }
+  else
+  {
+    SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
+    myFaces.Add(face);
+    myInfo.myNbQuadrangles++;
+    return face;
+  }
 }
 
-//=======================================================================
-//function : CreateEdge
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a node and all the elements which own this node
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateEdge(const Standard_Integer ID,
-                                              const Standard_Integer idnode1,
-                                              const Standard_Integer idnode2) const
+void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 {
-  Handle(SMDS_MeshEdge) edge = new SMDS_MeshEdge(ID,idnode1,idnode2);
-  return edge;
+        RemoveElement(node, true);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an edge and all the elements which own this edge
+///////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-//function : CreateFace
-//purpose  : 
-//=======================================================================
-
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateFace(const Standard_Integer ID,
-                                              const Standard_Integer idnode1,
-                                              const Standard_Integer idnode2,
-                                              const Standard_Integer idnode3) const
+void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
 {
-  Handle(SMDS_MeshFace) face = new SMDS_MeshTriangle(ID,idnode1,idnode2,idnode3);
-  return face;
+  RemoveElement(elem0d,true);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an edge and all the elements which own this edge
+///////////////////////////////////////////////////////////////////////////////
 
-//=======================================================================
-//function : CreateFace
-//purpose  : 
-//=======================================================================
-
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateFace(const Standard_Integer ID,
-                                              const Standard_Integer idnode1,
-                                              const Standard_Integer idnode2,
-                                              const Standard_Integer idnode3,
-                                              const Standard_Integer idnode4) const
+void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
 {
-  Handle(SMDS_MeshFace) face = new SMDS_MeshQuadrangle(ID,idnode1,idnode2,idnode3,idnode4);
-  return face;
+        RemoveElement(edge,true);
 }
 
-//=======================================================================
-//function : CreateVolume
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an face and all the elements which own this face
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateVolume(const Standard_Integer ID,
-                                                const Standard_Integer idnode1,
-                                                const Standard_Integer idnode2,
-                                                const Standard_Integer idnode3,
-                                                const Standard_Integer idnode4) const
+void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
 {
-  Handle(SMDS_MeshVolume) volume = new SMDS_MeshTetrahedron(ID,idnode1,idnode2,idnode3,idnode4);
-  return volume;
+        RemoveElement(face, true);
 }
 
-//=======================================================================
-//function : CreateVolume
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Remove a volume
+///////////////////////////////////////////////////////////////////////////////
 
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateVolume(const Standard_Integer ID,
-                                                const Standard_Integer idnode1,
-                                                const Standard_Integer idnode2,
-                                                const Standard_Integer idnode3,
-                                                const Standard_Integer idnode4,
-                                                const Standard_Integer idnode5) const
+void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 {
-  Handle(SMDS_MeshVolume) volume = new SMDS_MeshPyramid(ID,idnode1,idnode2,idnode3,idnode4,idnode5);
-  return volume;
+        RemoveElement(volume, true);
 }
 
 //=======================================================================
-//function : CreateVolume
-//purpose  : 
+//function : RemoveFromParent
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateVolume(const Standard_Integer ID,
-                                                const Standard_Integer idnode1,
-                                                const Standard_Integer idnode2,
-                                                const Standard_Integer idnode3,
-                                                const Standard_Integer idnode4,
-                                                const Standard_Integer idnode5,
-                                                const Standard_Integer idnode6) const
+bool SMDS_Mesh::RemoveFromParent()
 {
-  Handle(SMDS_MeshVolume) volume = new SMDS_MeshPrism(ID,idnode1,idnode2,idnode3,idnode4,idnode5,idnode6);
-  return volume;
+        if (myParent==NULL) return false;
+        else return (myParent->RemoveSubMesh(this));
 }
 
 //=======================================================================
-//function : CreateVolume
-//purpose  : 
+//function : RemoveSubMesh
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::CreateVolume(const Standard_Integer ID,
-                                                const Standard_Integer idnode1,
-                                                const Standard_Integer idnode2,
-                                                const Standard_Integer idnode3,
-                                                const Standard_Integer idnode4,
-                                                const Standard_Integer idnode5,
-                                                const Standard_Integer idnode6,
-                                                const Standard_Integer idnode7,
-                                                const Standard_Integer idnode8) const
+bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
 {
-  Handle(SMDS_MeshVolume) volume = new SMDS_MeshHexahedron(ID,idnode1,idnode2,idnode3,idnode4,
-                                                          idnode5,idnode6,idnode7,idnode8);
-  return volume;
+        bool found = false;
+
+        list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+        for (; itmsh!=myChildren.end() && !found; itmsh++)
+        {
+                SMDS_Mesh * submesh = *itmsh;
+                if (submesh == aMesh)
+                {
+                        found = true;
+                        myChildren.erase(itmsh);
+                }
+        }
+
+        return found;
 }
 
 //=======================================================================
-//function : Contains
-//purpose  : 
+//function : ChangeElementNodes
+//purpose  :
 //=======================================================================
 
-Standard_Boolean SMDS_Mesh::Contains(const Handle(SMDS_MeshElement)& elem) const
+bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
+                                   const SMDS_MeshNode    * nodes[],
+                                   const int                nbnodes)
 {
-  Standard_Boolean isinmesh = Standard_False;
-  if (myNodes.Contains(elem))
-    isinmesh = Standard_True;
-  else if (myEdges.Contains(elem))
-    isinmesh = Standard_True;
-  else if (myFaces.Contains(elem))
-    isinmesh = Standard_True;
-  else if (myVolumes.Contains(elem))
-    isinmesh = Standard_True;
+  // keep current nodes of elem
+  set<const SMDS_MeshElement*> oldNodes;
+  SMDS_ElemIteratorPtr itn = element->nodesIterator();
+  while(itn->more())
+    oldNodes.insert(  itn->next() );
 
-  return isinmesh;
+  if ( !element->IsPoly() )
+    myInfo.remove( element ); // element may change type
+
+  // change nodes
+  bool Ok = false;
+  SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
+  switch ( elem->GetType() )
+  {
+  case SMDSAbs_0DElement: {
+    if ( SMDS_Mesh0DElement* elem0d = dynamic_cast<SMDS_Mesh0DElement*>( elem ))
+      Ok = elem0d->ChangeNode( nodes[0] );
+    break;
+  }
+  case SMDSAbs_Edge: {
+    if ( nbnodes == 2 ) {
+      if ( SMDS_MeshEdge* edge = dynamic_cast<SMDS_MeshEdge*>( elem ))
+        Ok = edge->ChangeNodes( nodes[0], nodes[1] );
+    }
+    else if ( nbnodes == 3 ) {
+      if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
+        Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
+    }
+    break;
+  }
+  case SMDSAbs_Face: {
+    if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
+      Ok = face->ChangeNodes( nodes, nbnodes );
+    else
+      if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
+        Ok = QF->ChangeNodes( nodes, nbnodes );
+      else
+        if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
+          Ok = face->ChangeNodes(nodes, nbnodes);
+    break;
+  }
+  case SMDSAbs_Volume: {
+    if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
+      Ok = vol->ChangeNodes( nodes, nbnodes );
+    else
+      if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
+        Ok = QV->ChangeNodes( nodes, nbnodes );
+    break;
+  }
+  default:
+    MESSAGE ( "WRONG ELEM TYPE");
+  }
+
+  if ( Ok ) { // update InverseElements
+
+    set<const SMDS_MeshElement*>::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( elem );
+      else
+        // remove from oldNodes a node that remains in elem
+        oldNodes.erase( it );
+    }
+    // RemoveInverseElement from the nodes removed from elem
+    for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
+    {
+      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
+        (const_cast<SMDS_MeshElement *>( *it ));
+      n->RemoveInverseElement( elem );
+    }
+  }
+
+  if ( !element->IsPoly() )
+    myInfo.add( element ); // element may change type
+
+  return Ok;
 }
 
 //=======================================================================
-//function : FindEdge
-//purpose  : 
+//function : ChangePolyhedronNodes
+//purpose  : to change nodes of polyhedral volume
 //=======================================================================
-
-Handle(SMDS_MeshElement) SMDS_Mesh::FindEdge(const Handle(SMDS_MeshElement)& edge) const
+bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
+                                       const vector<const SMDS_MeshNode*>& nodes,
+                                       const vector<int>                 & quantities)
 {
-  Handle(SMDS_MeshElement) elem;
-  if (myEdges.Contains(edge))
-    elem = myEdges.Find(edge);
+  if (elem->GetType() != SMDSAbs_Volume) {
+    MESSAGE("WRONG ELEM TYPE");
+    return false;
+  }
+
+  const SMDS_PolyhedralVolumeOfNodes* vol = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>(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
+  bool Ok = const_cast<SMDS_PolyhedralVolumeOfNodes*>(vol)->ChangeNodes(nodes, quantities);
+  if (!Ok) {
+    return false;
+  }
 
-  return elem;
+  // 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);
+    }
+  }
+
+  // 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 : FindFace
-//purpose  : 
+//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);
+}
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindFace(const Handle(SMDS_MeshElement)& face) const
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
 {
-  Handle(SMDS_MeshElement) elem;
-  if (myFaces.Contains(face))
-    elem = myFaces.Find(face);
+  if (!node) return 0;
+  const SMDS_Mesh0DElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->NbNodes() == 1) {
+      toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
+    }
+  }
+  return toReturn;
+}
 
-  return elem;
+//=======================================================================
+//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 : FindVolume
-//purpose  : 
+//function : FindEdge
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindVolume(const Handle(SMDS_MeshElement)& volume) const
+const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
 {
-  Handle(SMDS_MeshElement) elem;
-  if (myVolumes.Contains(volume))
-    elem = myVolumes.Find(volume);
+  const SMDS_MeshNode * node1=FindNode(idnode1);
+  const SMDS_MeshNode * node2=FindNode(idnode2);
+  if((node1==NULL)||(node2==NULL)) return NULL;
+  return FindEdge(node1,node2);
+}
 
-  return elem;
+//#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 ) {
+      toReturn = static_cast<const SMDS_MeshEdge*>( e );
+      break;
+    }
+  }
+  //PROFILER_Get(1);
+  return toReturn;
 }
 
 
 //=======================================================================
-//function : FreeNode
-//purpose  : 
+//function : FindEdgeOrCreate
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::FreeNode(const Handle(SMDS_MeshElement)& node)
+SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
+                                           const SMDS_MeshNode * node2)
 {
-    myNodes.Remove(node);
+  if ( !node1 || !node2) return 0;
+  SMDS_MeshEdge * toReturn=NULL;
+  toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
+  if(toReturn==NULL) {
+    if ( myEdges.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+    toReturn=new SMDS_MeshEdge(node1,node2);
+    myEdges.Add(toReturn);
+    myInfo.myNbEdges++;
+  }
+  return toReturn;
+}
+
 
-    SMDS_ListIteratorOfListOfMesh itmsh(myChildren);
-    for (;itmsh.More(); itmsh.Next()) {
-      const Handle(SMDS_Mesh)& submesh = itmsh.Value();
-      submesh->RemoveNode(node->GetID());
+//=======================================================================
+//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)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshEdge *> (e);
     }
+  }
+  return 0;
 }
 
 
-
-//=======================================================================
-//function : RemoveNode
-//purpose  : 
 //=======================================================================
+//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)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
+}
 
-void SMDS_Mesh::RemoveNode(const Standard_Integer IDnode)
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+                                           const SMDS_MeshNode *node2,
+                                           const SMDS_MeshNode *node3)
 {
-  // find the MeshNode corresponding to IDnode
-  Handle(SMDS_MeshElement) node = FindNode(IDnode);
-  if (RemoveNode(node)) {
-    if (myParent.IsNull()) { // if no parent we can release the ID
-      myNodeIDFactory->ReleaseID(IDnode);
-    }
+  SMDS_MeshFace * toReturn=NULL;
+  toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
+  if(toReturn==NULL) {
+    toReturn = createTriangle(node1,node2,node3);
   }
-  
+  return toReturn;
 }
 
+
 //=======================================================================
-//function : RemoveNode
-//purpose  : 
-//=======================================================================
+//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,
+                                         const SMDS_MeshNode *node4)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 4 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
+}
 
-Standard_Boolean SMDS_Mesh::RemoveNode(const Handle(SMDS_MeshElement)& node)
+SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
+                                           const SMDS_MeshNode *node2,
+                                           const SMDS_MeshNode *node3,
+                                           const SMDS_MeshNode *node4)
 {
-  Standard_Boolean successRemove = Standard_False;
+  SMDS_MeshFace * toReturn=NULL;
+  toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
+  if(toReturn==NULL) {
+    toReturn=createQuadrangle(node1,node2,node3,node4);
+  }
+  return toReturn;
+}
+
 
-  if (!node.IsNull()) {
-    if (myHasInverse && myNodes.Contains(node)) {
-      SMDS_MapOfMeshOrientedElement map(1);
-      BuildMapNodeAncestors(node,map);
-      RemoveAncestors(node,map);
+//=======================================================================
+//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,
+                                         const SMDS_MeshNode *node4,
+                                         const SMDS_MeshNode *node5,
+                                         const SMDS_MeshNode *node6)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 6 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
+    }
+  }
+  return 0;
+}
+
+
+//=======================================================================
+//function : FindFace
+//purpose  : quadratic quadrangle
+//=======================================================================
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
+                                         int idnode3, int idnode4,
+                                         int idnode5, int idnode6,
+                                         int idnode7, int idnode8) const
+{
+  const SMDS_MeshNode * node1 = FindNode(idnode1);
+  const SMDS_MeshNode * node2 = FindNode(idnode2);
+  const SMDS_MeshNode * node3 = FindNode(idnode3);
+  const SMDS_MeshNode * node4 = FindNode(idnode4);
+  const SMDS_MeshNode * node5 = FindNode(idnode5);
+  const SMDS_MeshNode * node6 = FindNode(idnode6);
+  const SMDS_MeshNode * node7 = FindNode(idnode7);
+  const SMDS_MeshNode * node8 = FindNode(idnode8);
+  return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
+}
+
+const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
+                                         const SMDS_MeshNode *node2,
+                                         const SMDS_MeshNode *node3,
+                                         const SMDS_MeshNode *node4,
+                                         const SMDS_MeshNode *node5,
+                                         const SMDS_MeshNode *node6,
+                                         const SMDS_MeshNode *node7,
+                                         const SMDS_MeshNode *node8)
+{
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
+  while(it1->more()) {
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 8 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 &&
+            n!=node7 &&
+            n!=node8 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
     }
-
-    FreeNode(node);
-    successRemove = Standard_True;
   }
-
-  return successRemove;
+  return 0;
 }
 
+
 //=======================================================================
-//function : RemoveEdge
-//purpose  : 
+//function : FindElement
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveEdge(const Standard_Integer idnode1, const Standard_Integer idnode2)
+const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 {
-  Handle(SMDS_MeshElement) edge = FindEdge(idnode1,idnode2);
-  RemoveEdge(edge);
+  return myElementIDFactory->MeshElement(IDelem);
 }
 
 //=======================================================================
-//function : RemoveEdge
-//purpose  : 
+//function : FindFace
+//purpose  : find polygon
 //=======================================================================
 
-void SMDS_Mesh::RemoveEdge(const Handle(SMDS_MeshElement)& edge)
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
 {
-
-  if (!edge.IsNull()) {
-    myEdges.Remove(edge);
-
-    myElementIDFactory->ReleaseID(edge->GetID());
+  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)
+{
+  return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
+}
+
+
+//================================================================================
+/*!
+ * \brief Return element based on all given nodes
+ *  \param nodes - node of element
+ *  \param type - type of element
+ *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
+ *  \retval const SMDS_MeshElement* - found element or NULL
+ */
+//================================================================================
+
+const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
+                                                const SMDSAbs_ElementType            type,
+                                                const bool                           noMedium)
+{
+  if ( nodes.size() > 0 && nodes[0] )
+  {
+    SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
+    while (itF->more())
+    {
+      const SMDS_MeshElement* e = itF->next();
+      int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
+      if ( nbNodesToCheck == nodes.size() )
+      {
+        for ( int i = 1; e && i < nodes.size(); ++ i )
+        {
+          int nodeIndex = e->GetNodeIndex( nodes[ i ]);
+          if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
+            e = 0;
+        }
+        if ( e )
+          return static_cast<const SMDS_MeshFace *> (e);
+      }
+    }
+  }
+  return NULL;
 }
 
-
 //=======================================================================
-//function : RemoveFace
-//purpose  : 
+//function : DumpNodes
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveFace(const Standard_Integer idnode1, 
-                          const Standard_Integer idnode2,
-                          const Standard_Integer idnode3)
+void SMDS_Mesh::DumpNodes() const
 {
-  Handle(SMDS_MeshElement) face = FindFace(idnode1,idnode2,idnode3);
-  RemoveFace(face);
+        MESSAGE("dump nodes of mesh : ");
+        SMDS_NodeIteratorPtr itnode=nodesIterator();
+        while(itnode->more()) MESSAGE(itnode->next());
 }
 
 //=======================================================================
-//function : RemoveFace
-//purpose  : 
+//function : Dump0DElements
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::RemoveFace(const Standard_Integer idnode1, 
-                          const Standard_Integer idnode2,
-                          const Standard_Integer idnode3,
-                          const Standard_Integer idnode4)
+void SMDS_Mesh::Dump0DElements() const
 {
-  Handle(SMDS_MeshElement) face = FindFace(idnode1,idnode2,idnode3,idnode4);
-  RemoveFace(face);
+  MESSAGE("dump 0D elements of mesh : ");
+  SMDS_0DElementIteratorPtr it0d = elements0dIterator();
+  while(it0d->more()) MESSAGE(it0d->next());
 }
 
-
 //=======================================================================
-//function : RemoveFace
-//purpose  : 
+//function : DumpEdges
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveFace(const Handle(SMDS_MeshElement)& face)
+void SMDS_Mesh::DumpEdges() const
 {
-  if (!face.IsNull()) {
-    myFaces.Remove(face);
-    myElementIDFactory->ReleaseID(face->GetID());
-  }
+        MESSAGE("dump edges of mesh : ");
+        SMDS_EdgeIteratorPtr itedge=edgesIterator();
+        while(itedge->more()) MESSAGE(itedge->next());
 }
 
 //=======================================================================
-//function : RemoveVolume
-//purpose  : 
+//function : DumpFaces
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveVolume(const Handle(SMDS_MeshElement)& volume)
+void SMDS_Mesh::DumpFaces() const
 {
-  if (myVolumes.Contains(volume)) {
-    myVolumes.Remove(volume);
-    myElementIDFactory->ReleaseID(volume->GetID());
-  }
+        MESSAGE("dump faces of mesh : ");
+        SMDS_FaceIteratorPtr itface=facesIterator();
+        while(itface->more()) MESSAGE(itface->next());
 }
 
 //=======================================================================
-//function : RemoveElement
-//purpose  : 
+//function : DumpVolumes
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveElement(const Standard_Integer IDelem,const Standard_Boolean removenodes)
+void SMDS_Mesh::DumpVolumes() const
 {
-  Handle(SMDS_MeshElement) elem =  myElementIDFactory->MeshElement(IDelem);
-  RemoveElement(elem,removenodes);
-
-
-    
+        MESSAGE("dump volumes of mesh : ");
+        SMDS_VolumeIteratorPtr itvol=volumesIterator();
+        while(itvol->more()) MESSAGE(itvol->next());
 }
 
 //=======================================================================
-//function : RemoveElement
-//purpose  : 
+//function : DebugStats
+//purpose  :
 //=======================================================================
 
-void SMDS_Mesh::RemoveElement(const Handle(SMDS_MeshElement)& elem,const Standard_Boolean removenodes)
+void SMDS_Mesh::DebugStats() const
 {
-  if ( elem->IsKind(STANDARD_TYPE(SMDS_MeshEdge)) ) {
-    RemoveEdge(elem);
-  } else if ( elem->IsKind(STANDARD_TYPE(SMDS_MeshNode))) {
-    RemoveNode(elem);
-    return;
-  } else if ( elem->IsKind(STANDARD_TYPE(SMDS_MeshFace))) {
-    RemoveFace(elem);
-  } else if ( elem->IsKind(STANDARD_TYPE(SMDS_MeshVolume))) {
-    RemoveVolume(elem);
-  } else {
-    MESSAGE( "remove function : unknown type" );
-    return;
-  }
+  MESSAGE("Debug stats of mesh : ");
 
-  Standard_Integer nbcnx = elem->NbNodes();
-  Standard_Integer i;
-  for (i=1; i <= nbcnx; ++i) {
-    RemoveInverseElement(GetNode(i,elem),elem);
-    
-  }
+  MESSAGE("===== NODES ====="<<NbNodes());
+  MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
+  MESSAGE("===== EDGES ====="<<NbEdges());
+  MESSAGE("===== FACES ====="<<NbFaces());
+  MESSAGE("===== VOLUMES ====="<<NbVolumes());
+
+  MESSAGE("End Debug stats of mesh ");
+
+  //#ifdef DEB
 
-  if (removenodes) {
-    for (i=1; i <= nbcnx; ++i) {
-      if (GetNode(i,elem)->InverseElements().IsEmpty())
-       FreeNode(GetNode(i,elem));
+  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())
+    {
+      const SMDS_MeshElement *me = it->next();
+      sizeofnodes += sizeof(me);
     }
   }
 
-}
-//=======================================================================
-//function : RemoveFromParent
-//purpose  : 
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::RemoveFromParent()
-{
-  if (myParent.IsNull())
-    return Standard_False;
+  SMDS_FaceIteratorPtr itface=facesIterator();
+  while(itface->more())
+  {
+    const SMDS_MeshElement *face = itface->next();
+    sizeoffaces += sizeof(*face);
+  }
 
-  return (myParent->RemoveSubMesh(this));
+  MESSAGE("total size of node elements = " << sizeofnodes);;
+  MESSAGE("total size of face elements = " << sizeoffaces);;
 
+  //#endif
 }
 
-//=======================================================================
-//function : RemoveSubMesh
-//purpose  : 
-//=======================================================================
-
-Standard_Boolean SMDS_Mesh::RemoveSubMesh(const Handle(SMDS_Mesh)& aMesh)
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of nodes
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbNodes() const
 {
-  Standard_Boolean found = Standard_False;
+        return myNodes.Size();
+}
 
-  SMDS_ListIteratorOfListOfMesh itmsh(myChildren);
-  for (;itmsh.More() && !found; itmsh.Next()) {
-    Handle(SMDS_Mesh) submesh;
-    submesh = itmsh.Value();
-    if (submesh == aMesh) {
-      found = Standard_True;
-      myChildren.Remove(itmsh);
-    }
-  }
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::Nb0DElements() const
+{
+  return my0DElements.Size();
+}
 
-  return found;
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of edges (including construction edges)
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbEdges() const
+{
+        return myEdges.Size();
 }
 
-//=======================================================================
-//function : RemoveInverseElement
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of faces (including construction faces)
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbFaces() const
+{
+        return myFaces.Size();
+}
 
-void SMDS_Mesh::RemoveInverseElement(const Handle(SMDS_MeshElement)& elem, 
-                                    const Handle(SMDS_MeshElement)& parent) const
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of volumes
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbVolumes() const
 {
-  if (!myHasInverse) 
-    return;
+        return myVolumes.Size();
+}
 
-  Handle(SMDS_MeshNode)& node = *((Handle(SMDS_MeshNode)*)&elem);
-  node->RemoveInverseElement(parent);
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of child mesh of this mesh.
+/// Note that the tree structure of SMDS_Mesh seems to be unused in this version
+/// (2003-09-08) of SMESH
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbSubMesh() const
+{
+        return myChildren.size();
 }
-//=======================================================================
-//function : RemoveAncestors
-//purpose  : 
-//=======================================================================
 
-void SMDS_Mesh::RemoveAncestors(const Handle(SMDS_MeshElement)& elem,
-                               const SMDS_MapOfMeshOrientedElement& map)
+///////////////////////////////////////////////////////////////////////////////
+/// Destroy the mesh and all its elements
+/// All pointer on elements owned by this mesh become illegals.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh::~SMDS_Mesh()
 {
+  list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  while(itc!=myChildren.end())
+  {
+    delete *itc;
+    itc++;
+  }
 
-  if (!myHasInverse) 
-    return;
+  if(myParent==NULL)
+  {
+    delete myNodeIDFactory;
+    delete myElementIDFactory;
+  }
+  else
+  {
+    SMDS_ElemIteratorPtr eIt = elementsIterator();
+    while ( eIt->more() )
+      myElementIDFactory->ReleaseID(eIt->next()->GetID());
+    SMDS_NodeIteratorPtr itn = nodesIterator();
+    while (itn->more())
+      myNodeIDFactory->ReleaseID(itn->next()->GetID());
+  }
 
-  SMDS_MapIteratorOfExtendedOrientedMap itAnc(map);
+  SetOfNodes::Iterator itn(myNodes);
+  for (; itn.More(); itn.Next())
+    delete itn.Value();
 
-  for (;itAnc.More();itAnc.Next()) {
-    const Handle(SMDS_MeshElement)& ME = itAnc.Key();
-    Standard_Integer nbcnx = ME->NbNodes();
+  SetOf0DElements::Iterator it0d (my0DElements);
+  for (; it0d.More(); it0d.Next())
+  {
+    SMDS_MeshElement* elem = it0d.Value();
+    delete elem;
+  }
 
-    for (Standard_Integer i=1; i <= nbcnx; ++i) {
-      RemoveInverseElement(GetNode(i,ME),ME);
-    }
+  SetOfEdges::Iterator ite(myEdges);
+  for (; ite.More(); ite.Next())
+  {
+    SMDS_MeshElement* elem = ite.Value();
+    delete elem;
   }
 
-  SMDS_MapIteratorOfExtendedOrientedMap itAnc2(map);
+  SetOfFaces::Iterator itf(myFaces);
+  for (; itf.More(); itf.Next())
+  {
+    SMDS_MeshElement* elem = itf.Value();
+    delete elem;
+  }
 
-  for (;itAnc2.More();itAnc2.Next()) {
-    const Handle(SMDS_MeshElement)& ME = itAnc2.Key();
-    RemoveElement(ME);
+  SetOfVolumes::Iterator itv(myVolumes);
+  for (; itv.More(); itv.Next())
+  {
+    SMDS_MeshElement* elem = itv.Value();
+    delete elem;
   }
 }
 
-//=======================================================================
-//function : BuildMapNodeAncestors
-//purpose  : 
-//=======================================================================
+//================================================================================
+/*!
+ * \brief Clear all data
+ */
+//================================================================================
 
-void SMDS_Mesh::BuildMapNodeAncestors(const Handle(SMDS_MeshElement)& ME, 
-                                     SMDS_MapOfMeshOrientedElement& map) const
+void SMDS_Mesh::Clear()
 {
+  if (myParent!=NULL) {
+    SMDS_ElemIteratorPtr eIt = elementsIterator();
+    while ( eIt->more() )
+      myElementIDFactory->ReleaseID(eIt->next()->GetID());
+    SMDS_NodeIteratorPtr itn = nodesIterator();
+    while (itn->more())
+      myNodeIDFactory->ReleaseID(itn->next()->GetID());
+  }
+  else {
+    myNodeIDFactory->Clear();
+    myElementIDFactory->Clear();
+  }
 
-  if (!myHasInverse) 
-    return;
+  SMDS_VolumeIteratorPtr itv = volumesIterator();
+  while (itv->more())
+    delete itv->next();
+  myVolumes.Clear();
 
-  Standard_Integer nbcnx = ME->NbNodes();
+  SMDS_FaceIteratorPtr itf = facesIterator();
+  while (itf->more())
+    delete itf->next();
+  myFaces.Clear();
 
-  for (Standard_Integer i=1; i <= nbcnx; ++i) {
-    const SMDS_ListOfMeshElement& lstInvElements = GetNode(i,ME)->InverseElements();
+  SMDS_EdgeIteratorPtr ite = edgesIterator();
+  while (ite->more())
+    delete ite->next();
+  myEdges.Clear();
 
-    SMDS_ListIteratorOfListOfMeshElement it(lstInvElements);
-    for (;it.More();it.Next()) {
-      const Handle(SMDS_MeshElement)& meParent = it.Value();
-      if (Contains(meParent))
-       map.Add(meParent);
-    }
+  SMDS_0DElementIteratorPtr it0d = elements0dIterator();
+  while (it0d->more())
+    delete it0d->next();
+  my0DElements.Clear();
 
-  }
+  SMDS_NodeIteratorPtr itn = nodesIterator();
+  while (itn->more())
+    delete itn->next();
+  myNodes.Clear();
+
+  list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  while(itc!=myChildren.end())
+    (*itc)->Clear();
 
+  myInfo.Clear();
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-//=======================================================================
-//function : BuildMapEdgeAncestors
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-void SMDS_Mesh::BuildMapEdgeAncestors(const Handle(SMDS_MeshElement)& ME, 
-                                     SMDS_MapOfMeshOrientedElement& map) const
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-  if (!myHasInverse) 
-    return;
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-  Standard_Integer nbcnx = ME->NbNodes();
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-  for (Standard_Integer i=1; i <= nbcnx; ++i) {
-    const SMDS_ListOfMeshElement& lstInvElements = GetNode(i,ME)->InverseElements();
+///////////////////////////////////////////////////////////////////////////////
+/// 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;
+}
 
-    SMDS_ListIteratorOfListOfMeshElement it(lstInvElements);
-    for (;it.More();it.Next()) {
-      const Handle(SMDS_MeshElement)& meParent = it.Value();
-      if ( !meParent->IsKind(STANDARD_TYPE(SMDS_MeshEdge)) && Contains(meParent))
-       map.Add(meParent);
-    }
+namespace {
 
-  }
+  ///////////////////////////////////////////////////////////////////////////////
+  ///Iterator on NCollection_Map
+  ///////////////////////////////////////////////////////////////////////////////
+  template <class MAP, typename ELEM=const SMDS_MeshElement*, class FATHER=SMDS_ElemIterator>
+  struct MYNCollection_Map_Iterator: public FATHER
+  {
+    typename MAP::Iterator myIterator;
 
-}
+    MYNCollection_Map_Iterator(const MAP& map):myIterator(map){}
 
+    bool more()
+    {
+      while(myIterator.More())
+      {
+        if(myIterator.Value()->GetID()!=-1)
+          return true;
+        myIterator.Next();
+      }
+      return false;
+    }
 
-//=======================================================================
-//function : BuildMapFaceAncestors
-//purpose  : 
-//=======================================================================
+    ELEM next()
+    {
+      ELEM current = (ELEM) myIterator.Value();
+      myIterator.Next();
+      return current;
+    }
+  };
+  //================================================================================
+  /*!
+   * \brief Iterator on elements in id increasing order
+   */
+  //================================================================================
+
+  template <typename ELEM=const SMDS_MeshElement*>
+  class IdSortedIterator : public SMDS_Iterator<ELEM>
+  {
+    const 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;
 
-void SMDS_Mesh::BuildMapFaceAncestors(const Handle(SMDS_MeshElement)& ME, 
-                                     SMDS_MapOfMeshOrientedElement& map) const
-{
+      for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
+        if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
+            && myElem->GetType() != myType )
+          myElem = 0;
 
-  if (!myHasInverse) 
-    return;
+      myNbFound += bool(myElem);
 
-  Standard_Integer nbcnx = ME->NbNodes();
+      return current;
+    }
+  };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return an iterator on nodes of the current mesh factory
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
+{
+  typedef MYNCollection_Map_Iterator
+    < SetOfNodes, const SMDS_MeshNode*, SMDS_NodeIterator > TIterator;
+  typedef IdSortedIterator< const SMDS_MeshNode* >          TSortedIterator;
+  return ( idInceasingOrder ?
+           SMDS_NodeIteratorPtr( new TSortedIterator( *myNodeIDFactory, SMDSAbs_Node, NbNodes())) :
+           SMDS_NodeIteratorPtr( new TIterator(myNodes)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on 0D elements of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_0DElementIteratorPtr SMDS_Mesh::elements0dIterator(bool idInceasingOrder) const
+{
+  typedef MYNCollection_Map_Iterator
+    < SetOf0DElements, const SMDS_Mesh0DElement*, SMDS_0DElementIterator > TIterator;
+  typedef IdSortedIterator< const SMDS_Mesh0DElement* >                    TSortedIterator;
+  return ( idInceasingOrder ?
+           SMDS_0DElementIteratorPtr( new TSortedIterator( *myElementIDFactory,
+                                                           SMDSAbs_0DElement,
+                                                           Nb0DElements() )) :
+           SMDS_0DElementIteratorPtr( new TIterator(my0DElements)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on edges of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
+{
+  typedef MYNCollection_Map_Iterator
+    < SetOfEdges, const SMDS_MeshEdge*, SMDS_EdgeIterator > TIterator;
+  typedef IdSortedIterator< const SMDS_MeshEdge* >          TSortedIterator;
+  return ( idInceasingOrder ?
+           SMDS_EdgeIteratorPtr( new TSortedIterator( *myElementIDFactory,
+                                                      SMDSAbs_Edge,
+                                                      NbEdges() )) :
+           SMDS_EdgeIteratorPtr(new TIterator(myEdges)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on faces of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
+{
+  typedef MYNCollection_Map_Iterator
+    < SetOfFaces, const SMDS_MeshFace*, SMDS_FaceIterator > TIterator;
+  typedef IdSortedIterator< const SMDS_MeshFace* >          TSortedIterator;
+  return ( idInceasingOrder ?
+           SMDS_FaceIteratorPtr( new TSortedIterator( *myElementIDFactory,
+                                                      SMDSAbs_Face,
+                                                      NbFaces() )) :
+           SMDS_FaceIteratorPtr(new TIterator(myFaces)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Return an iterator on volumes of the current mesh.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
+{
+  typedef MYNCollection_Map_Iterator
+    < SetOfVolumes, const SMDS_MeshVolume*, SMDS_VolumeIterator > TIterator;
+  typedef IdSortedIterator< const SMDS_MeshVolume* >              TSortedIterator;
+  return ( idInceasingOrder ?
+           SMDS_VolumeIteratorPtr( new TSortedIterator( *myElementIDFactory,
+                                                        SMDSAbs_Volume,
+                                                        NbVolumes() )) :
+           SMDS_VolumeIteratorPtr(new TIterator(myVolumes)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return an iterator on elements of the current mesh factory
+///////////////////////////////////////////////////////////////////////////////
+SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
+{
+  switch (type) {
+  case SMDSAbs_All:
+    break;
+  case SMDSAbs_Volume:
+    return SMDS_ElemIteratorPtr (new MYNCollection_Map_Iterator< SetOfVolumes >(myVolumes));
+  case SMDSAbs_Face:
+    return SMDS_ElemIteratorPtr (new MYNCollection_Map_Iterator< SetOfFaces >(myFaces));
+  case SMDSAbs_Edge:
+    return SMDS_ElemIteratorPtr (new MYNCollection_Map_Iterator< SetOfEdges >(myEdges));
+  case SMDSAbs_0DElement:
+    return SMDS_ElemIteratorPtr (new MYNCollection_Map_Iterator< SetOf0DElements >(my0DElements));
+  case SMDSAbs_Node:
+    return myNodeIDFactory->elementsIterator();
+  default:;
+  }
+  return myElementIDFactory->elementsIterator();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Do intersection of sets (more than 2)
+///////////////////////////////////////////////////////////////////////////////
+static set<const SMDS_MeshElement*> * intersectionOfSets(
+        set<const SMDS_MeshElement*> vs[], int numberOfSets)
+{
+        set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
+        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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the list of finit elements owning the given element
+///////////////////////////////////////////////////////////////////////////////
+static 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_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
+                SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+
+                //initSet[i]=set<const SMDS_MeshElement*>();
+                while(itFe->more())
+                  initSet[i].insert(itFe->next());
+
+                i++;
+        }
+        set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
+        delete [] initSet;
+        return retSet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the list of nodes used only by the given elements
+///////////////////////////////////////////////////////////////////////////////
+static set<const SMDS_MeshElement*> * getExclusiveNodes(
+        set<const SMDS_MeshElement*>& elements)
+{
+        set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
+        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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Find the children of an element that are made of given nodes
+///@param setOfChildren The set in which matching children will be inserted
+///@param element The element were to search matching children
+///@param nodes The nodes that the children must have to be selected
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
+                                     const SMDS_MeshElement *      element,
+                                     set<const SMDS_MeshElement*>& nodes)
+{
+  switch(element->GetType())
+    {
+    case SMDSAbs_Node:
+      MESSAGE("Internal Error: This should not happend");
+      break;
+    case SMDSAbs_0DElement:
+      {
+      }
+      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);
+                }
+        }
+    }
+}
 
-  for (Standard_Integer i=1; i <= nbcnx; ++i) {
-    const SMDS_ListOfMeshElement& lstInvElements = GetNode(i,ME)->InverseElements();
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///@param removenodes if true remaining nodes will be removed
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
+                              const bool removenodes)
+{
+  list<const SMDS_MeshElement *> removedElems;
+  list<const SMDS_MeshElement *> removedNodes;
+  RemoveElement( elem, removedElems, removedNodes, removenodes );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///@param removedElems contains all removed elements
+///@param removedNodes contains 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)
+{
+  // get finite elements built on elem
+  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);
+  }
+  else
+    s1 = getFinitElements(elem);
+
+  // get exclusive nodes (which would become free afterwards)
+  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;
+  }
+  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();
+  while(it!=s1->end())
+  {
+    addChildrenWithNodes(s3, *it ,*s2);
+    s3.insert(*it);
+    it++;
+  }
+  if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
+
+  // remove finite and construction elements
+  it=s3.begin();
+  while(it!=s3.end())
+  {
+    // 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) );
+    }
 
-    SMDS_ListIteratorOfListOfMeshElement it(lstInvElements);
-    for (;it.More();it.Next()) {
-      const Handle(SMDS_MeshElement)& meParent = it.Value();
-      if ( !meParent->IsKind(STANDARD_TYPE(SMDS_MeshEdge))
-          && ( !meParent->IsKind(STANDARD_TYPE(SMDS_MeshFace))) && Contains(meParent) )
-       map.Add(meParent);
+    switch((*it)->GetType())
+    {
+    case SMDSAbs_Node:
+      MESSAGE("Internal Error: This should not happen");
+      break;
+    case SMDSAbs_0DElement:
+      my0DElements.Remove(static_cast<SMDS_Mesh0DElement*>
+                          (const_cast<SMDS_MeshElement*>(*it)));
+      //myInfo.Remove0DElement(*it);
+      myInfo.remove(*it);
+      break;
+    case SMDSAbs_Edge:
+      myEdges.Remove(static_cast<SMDS_MeshEdge*>
+                    (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveEdge(*it);
+      break;
+    case SMDSAbs_Face:
+      myFaces.Remove(static_cast<SMDS_MeshFace*>
+                    (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveFace(*it);
+      break;
+    case SMDSAbs_Volume:
+      myVolumes.Remove(static_cast<SMDS_MeshVolume*>
+                      (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveVolume(*it);
+      break;
     }
+    //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
+    removedElems.push_back( (*it) );
+    myElementIDFactory->ReleaseID((*it)->GetID());
+    delete (*it);
+    it++;
+  }
 
+  // remove exclusive (free) nodes
+  if(removenodes)
+  {
+    it=s2->begin();
+    while(it!=s2->end())
+    {
+      //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
+      myNodes.Remove(static_cast<SMDS_MeshNode*>
+                    (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.myNbNodes--;
+      myNodeIDFactory->ReleaseID((*it)->GetID());
+      removedNodes.push_back( (*it) );
+      delete *it;
+      it++;
+    }
   }
 
+  delete s2;
+  delete s1;
 }
 
 
-//=======================================================================
-//function : FindEdge
-//purpose  : 
-//=======================================================================
+///////////////////////////////////////////////////////////////////////////////
+///@param elem The element to delete
+///////////////////////////////////////////////////////////////////////////////
+void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
+{
+  SMDSAbs_ElementType aType = elem->GetType();
+  if (aType == SMDSAbs_Node) {
+    // only free node can be removed by this method
+    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>(elem);
+    SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+    if (!itFe->more()) { // free node
+      myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
+      myInfo.myNbNodes--;
+      myNodeIDFactory->ReleaseID(elem->GetID());
+      delete elem;
+    }
+  } else {
+    if (hasConstructionEdges() || hasConstructionFaces())
+      // this methods is only for meshes without descendants
+      return;
+
+    // Remove element from <InverseElements> of its nodes
+    SMDS_ElemIteratorPtr itn = elem->nodesIterator();
+    while (itn->more()) {
+      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
+        (const_cast<SMDS_MeshElement *>(itn->next()));
+      n->RemoveInverseElement(elem);
+    }
+
+    // in meshes without descendants elements are always free
+    switch (aType) {
+    case SMDSAbs_0DElement:
+      my0DElements.Remove(static_cast<SMDS_Mesh0DElement*>
+                          (const_cast<SMDS_MeshElement*>(elem)));
+      //myInfo.Remove0DElement(elem);
+      myInfo.remove(elem);
+      break;
+    case SMDSAbs_Edge:
+      myEdges.Remove(static_cast<SMDS_MeshEdge*>
+                     (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveEdge(elem);
+      break;
+    case SMDSAbs_Face:
+      myFaces.Remove(static_cast<SMDS_MeshFace*>
+                     (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveFace(elem);
+      break;
+    case SMDSAbs_Volume:
+      myVolumes.Remove(static_cast<SMDS_MeshVolume*>
+                       (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveVolume(elem);
+      break;
+    default:
+      break;
+    }
+    myElementIDFactory->ReleaseID(elem->GetID());
+    delete elem;
+  }
+}
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindEdge(const Standard_Integer idnode1,
-                                            const Standard_Integer idnode2 ) const
+/*!
+ * Checks if the element is present in mesh.
+ * Useful to determine dead pointers.
+ */
+bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
 {
-  Handle(SMDS_MeshEdge) edge = new SMDS_MeshEdge(0,idnode1,idnode2);
-  return FindEdge(edge);
+  // 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_0DElementIteratorPtr it0d = elements0dIterator();
+  while (it0d->more())
+    if (elem == it0d->next())
+      return true;
+  SMDS_EdgeIteratorPtr ite = edgesIterator();
+  while (ite->more())
+    if (elem == ite->next())
+      return true;
+  SMDS_FaceIteratorPtr itf = facesIterator();
+  while (itf->more())
+    if (elem == itf->next())
+      return true;
+  SMDS_VolumeIteratorPtr itv = volumesIterator();
+  while (itv->more())
+    if (elem == itv->next())
+      return true;
+  return false;
 }
 
 //=======================================================================
-//function : FindFace
-//purpose  : 
+//function : MaxNodeID
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindFace(const Standard_Integer idnode1,
-                                            const Standard_Integer idnode2,
-                                            const Standard_Integer idnode3 ) const
+int SMDS_Mesh::MaxNodeID() const
 {
-  Handle(SMDS_MeshFace) face = new SMDS_MeshTriangle(0,idnode1,idnode2,idnode3);
-  return FindFace(face);
+  return myNodeIDFactory->GetMaxID();
 }
 
 //=======================================================================
-//function : FindFace
-//purpose  : 
+//function : MinNodeID
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindFace(const Standard_Integer idnode1,
-                                            const Standard_Integer idnode2,
-                                            const Standard_Integer idnode3,
-                                            const Standard_Integer idnode4 ) const
+int SMDS_Mesh::MinNodeID() const
 {
-  Handle(SMDS_MeshFace) face = new SMDS_MeshQuadrangle(0,idnode1,idnode2,idnode3,idnode4);
-  return FindFace(face);
+  return myNodeIDFactory->GetMinID();
 }
 
 //=======================================================================
-//function : FindElement
-//purpose  : 
+//function : MaxElementID
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshElement) SMDS_Mesh::FindElement(const Standard_Integer IDelem) const
+int SMDS_Mesh::MaxElementID() const
 {
-  return myElementIDFactory->MeshElement(IDelem);
+  return myElementIDFactory->GetMaxID();
 }
 
 //=======================================================================
-//function : GetNode
-//purpose  : 
+//function : MinElementID
+//purpose  :
 //=======================================================================
 
-Handle(SMDS_MeshNode) SMDS_Mesh::GetNode(const Standard_Integer rank, 
-                                        const Handle(SMDS_MeshElement)& ME) const
-
+int SMDS_Mesh::MinElementID() const
 {
-  const Standard_Integer idnode = ME->GetConnection(rank); // take care, no control of bounds
-
-  Handle(SMDS_MeshElement) elem = FindNode(idnode);
-  Handle(SMDS_MeshNode)& node = *((Handle(SMDS_MeshNode)*)&elem);
-  return node;
-
+  return myElementIDFactory->GetMinID();
 }
 
-
 //=======================================================================
-//function : DumpNodes
-//purpose  : 
+//function : Renumber
+//purpose  : Renumber all nodes or elements.
 //=======================================================================
 
-void SMDS_Mesh::DumpNodes() const
+void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
 {
-  MESSAGE( "dump nodes of mesh : " );
+  if ( deltaID == 0 )
+    return;
 
-  SMDS_MapIteratorOfExtendedOrientedMap itnode(myNodes);
+  SMDS_MeshElementIDFactory * idFactory =
+    isNodes ? myNodeIDFactory : myElementIDFactory;
 
-  for (;itnode.More();itnode.Next()) {
-    const Handle(SMDS_MeshElement)& node = itnode.Key();
-    MESSAGE( node);
-    
+  // 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 : DumpEdges
-//purpose  : 
+//function : GetElementType
+//purpose  : Return type of element or node with id
 //=======================================================================
 
-void SMDS_Mesh::DumpEdges() const
+SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
 {
-  MESSAGE( "dump edges of mesh : " );
-
-  SMDS_MapIteratorOfExtendedOrientedMap itedge(myEdges);
+  SMDS_MeshElement* elem = 0;
+  if( iselem )
+    elem = myElementIDFactory->MeshElement( id );
+  else
+    elem = myNodeIDFactory->MeshElement( id );
 
-  for (;itedge.More();itedge.Next()) {
-    const Handle(SMDS_MeshElement)& edge = itedge.Key();
-    MESSAGE( edge);
+  if( !elem )
+  {
+    //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
+    return SMDSAbs_All;
   }
+  else
+    return elem->GetType();
 }
 
 
 
+//********************************************************************
+//********************************************************************
+//********                                                   *********
+//*****       Methods for addition of quadratic elements        ******
+//********                                                   *********
+//********************************************************************
+//********************************************************************
+
 //=======================================================================
-//function : DumpFaces
-//purpose  : 
+//function : AddEdgeWithID
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::DumpFaces() const
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
 {
-  MESSAGE( "dump faces of mesh : " );
-
-  SMDS_MapIteratorOfExtendedOrientedMap itface(myFaces);
-
-  for (;itface.More();itface.Next()) {
-    const Handle(SMDS_MeshElement)& face = itface.Key();
-    MESSAGE( face);
-  }
+  return SMDS_Mesh::AddEdgeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     ID);
 }
 
-
 //=======================================================================
-//function : DumpVolumes
-//purpose  : 
+//function : AddEdge
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::DumpVolumes() const
+SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
+                                  const SMDS_MeshNode* n2,
+                                  const SMDS_MeshNode* n12)
 {
-  MESSAGE( "dump volumes of mesh : " );
-
-  SMDS_MapIteratorOfExtendedOrientedMap itvol(myVolumes);
+  return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
+}
 
-  for (;itvol.More();itvol.Next()) {
-    const Handle(SMDS_MeshElement)& volume = itvol.Key();
-    MESSAGE( volume);
+//=======================================================================
+//function : AddEdgeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n12,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n12 ) return 0;
+  SMDS_QuadraticEdge* edge = new SMDS_QuadraticEdge(n1,n2,n12);
+  if(myElementIDFactory->BindID(ID, edge)) {
+    SMDS_MeshNode *node1,*node2, *node12;
+    node1 = const_cast<SMDS_MeshNode*>(n1);
+    node2 = const_cast<SMDS_MeshNode*>(n2);
+    node12 = const_cast<SMDS_MeshNode*>(n12);
+    node1->AddInverseElement(edge);
+    node2->AddInverseElement(edge);
+    node12->AddInverseElement(edge);
+    myEdges.Add(edge);
+    myInfo.myNbQuadEdges++;
+    return edge;
+  }
+  else {
+    delete edge;
+    return NULL;
   }
 }
 
 
-
 //=======================================================================
-//function : DebugStats
-//purpose  : 
+//function : AddFace
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::DebugStats() const
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n31)
 {
-  //VRV: T2.4 impossible to use Logger server
-  MESSAGE( "Debug stats of mesh : " );
-
-  MESSAGE( "===== NODES =====" );
-  myNodes.Statistics(cout);
-
-  MESSAGE( "===== EDGES =====" );
-  myEdges.Statistics(cout);
-
-  MESSAGE( "===== FACES =====" );
-  myFaces.Statistics(cout);
-
-  MESSAGE( "===== VOLUMES =====" );
-  myVolumes.Statistics(cout);
-  //VRV: T2.4 impossible to use Logger server
-
-  MESSAGE( "End Debug stats of mesh " );
-
-  //#ifdef DEB
-  SMDS_MapIteratorOfExtendedOrientedMap itnode(myNodes);
-  Standard_Integer sizeofnodes = 0;
-  Standard_Integer sizeoffaces = 0;
-
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
+                                  myElementIDFactory->GetFreeID());
+}
 
-  for (;itnode.More();itnode.Next()) {
-    const Handle(SMDS_MeshElement)& node = itnode.Key();
-    
-    Standard_Transient *p = node->This();
-    sizeofnodes += sizeof( *((SMDS_MeshNode *)p) );
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
+                                        int n12,int n23,int n31, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID
+    ((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);
+}
 
-    SMDS_ListIteratorOfListOfMeshElement it(node->InverseElements());
-    for (;it.More();it.Next()) {
-      const Handle(SMDS_MeshElement)& me = it.Value();
-      sizeofnodes += sizeof(me);
-    }
-    
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n31,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
+  if(hasConstructionEdges()) {
+    // creation quadratic edges - not implemented
+    return 0;
   }
-
-  SMDS_MapIteratorOfExtendedOrientedMap itface(myFaces);
-
-  for (;itface.More();itface.Next()) {
-    const Handle(SMDS_MeshElement)& face = itface.Key();
-    
-    Standard_Transient *p = face->This();
-    sizeoffaces += sizeof( *((SMDS_MeshFace *)p) );
-    
+  SMDS_QuadraticFaceOfNodes* face =
+    new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
+  myFaces.Add(face);
+  myInfo.myNbQuadTriangles++;
+
+  if (!registerElement(ID, face)) {
+    RemoveElement(face, false);
+    face = NULL;
   }
-  MESSAGE( "total size of node elements = " << sizeofnodes );;
-  MESSAGE( "total size of face elements = " << sizeoffaces );;
+  return face;
+}
 
-  //#endif
 
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n34,
+                                  const SMDS_MeshNode * n41)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
+                                  myElementIDFactory->GetFreeID());
 }
 
 //=======================================================================
-//function : RebuildAllInverseConnections
-//purpose  : 
+//function : AddFaceWithID
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::RebuildAllInverseConnections()
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
+                                        int n12,int n23,int n34,int n41, int ID)
 {
-  if (!myParent.IsNull())
-    myParent->RebuildAllInverseConnections();
-
-  else {
-    // Clear all inverseconnections from nodes
-    SMDS_MapIteratorOfExtendedOrientedMap itnode(myNodes);
-    
-    for (;itnode.More();itnode.Next()) {
-      const Handle(SMDS_MeshElement)& elem = itnode.Key();
-      elem->ClearInverseElements();
-    }
-    
-
-    RebuildInverseConnections();
-
-    SMDS_ListIteratorOfListOfMesh itmsh(myChildren);
-    for (;itmsh.More(); itmsh.Next()) {
-      Handle(SMDS_Mesh) submesh;
-      submesh = itmsh.Value();
-    
-      submesh->RebuildInverseConnections();
-
-    }
-  }
+  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);
 }
 
 //=======================================================================
-//function : RebuildInverseConnections
-//purpose  : 
+//function : AddFaceWithID
+//purpose  :
 //=======================================================================
-
-void SMDS_Mesh::RebuildInverseConnections()
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
+                                        int ID)
 {
-  // rebuld inverse connections to volumes
-  SMDS_MapIteratorOfExtendedOrientedMap itvol(myVolumes);
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
+  if(hasConstructionEdges()) {
+    // creation quadratic edges - not implemented
+  }
+  SMDS_QuadraticFaceOfNodes* face =
+    new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
+  myFaces.Add(face);
+  myInfo.myNbQuadQuadrangles++;
+
+  if (!registerElement(ID, face)) {
+    RemoveElement(face, false);
+    face = NULL;
+  }
+  return face;
+}
 
-  for (;itvol.More();itvol.Next()) {
-    const Handle(SMDS_MeshElement)& vol = itvol.Key();
 
-    Standard_Integer nbcnx = vol->NbNodes();
-    for (Standard_Integer inode=1; inode<=nbcnx; ++inode) {
-      Standard_Integer idnode = vol->GetConnection(inode);
-      Handle(SMDS_MeshElement) node = FindNode(idnode);
-      if (!node.IsNull())
-       node->AddInverseElement(vol);
-    }
-    
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n31,
+                                      const SMDS_MeshNode * n14,
+                                      const SMDS_MeshNode * n24,
+                                      const SMDS_MeshNode * n34)
+{
+  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;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n12,int n23,int n31,
+                                            int n14,int n24,int n34, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((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);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order tetrahedron of 10 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n31,
+                                            const SMDS_MeshNode * n14,
+                                            const SMDS_MeshNode * n24,
+                                            const SMDS_MeshNode * n34,
+                                            int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
+    return 0;
+  if(hasConstructionFaces()) {
+    // creation quadratic faces - not implemented
+    return 0;
   }
+  SMDS_QuadraticVolumeOfNodes * volume =
+    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
+  myVolumes.Add(volume);
+  myInfo.myNbQuadTetras++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
+}
 
-  // rebuld inverse connections to faces
-  SMDS_MapIteratorOfExtendedOrientedMap itface(myFaces);
-
-  for (;itface.More();itface.Next()) {
-    const Handle(SMDS_MeshElement)& face = itface.Key();
 
-    Standard_Integer nbcnx = face->NbNodes();
-    for (Standard_Integer inode=1; inode<=nbcnx; ++inode) {
-      Standard_Integer idnode = face->GetConnection(inode);
-      Handle(SMDS_MeshElement) node = FindNode(idnode);
-      if (!node.IsNull())
-       node->AddInverseElement(face);
-    }
-    
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n25,
+                                      const SMDS_MeshNode * n35,
+                                      const SMDS_MeshNode * n45)
+{
+  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;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
+                                            int n12,int n23,int n34,int n41,
+                                            int n15,int n25,int n35,int n45, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((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);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order pyramid of 13 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n25,
+                                            const SMDS_MeshNode * n35,
+                                            const SMDS_MeshNode * n45,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
+      !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
+    return 0;
+  if(hasConstructionFaces()) {
+    // creation quadratic faces - not implemented
+    return 0;
   }
+  SMDS_QuadraticVolumeOfNodes * volume =
+    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
+                                    n34,n41,n15,n25,n35,n45);
+  myVolumes.Add(volume);
+  myInfo.myNbQuadPyramids++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
+}
 
-  // rebuld inverse connections to edges
-  SMDS_MapIteratorOfExtendedOrientedMap itedge(myEdges);
-
-  for (;itedge.More();itedge.Next()) {
-    const Handle(SMDS_MeshElement)& edge = itedge.Key();
 
-    Standard_Integer nbcnx = edge->NbNodes();
-    for (Standard_Integer inode=1; inode<=nbcnx; ++inode) {
-      Standard_Integer idnode = edge->GetConnection(inode);
-      Handle(SMDS_MeshElement) node = FindNode(idnode);
-      if (!node.IsNull())
-       node->AddInverseElement(edge);
-    }
-    
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n31,
+                                      const SMDS_MeshNode * n45,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n64,
+                                      const SMDS_MeshNode * n14,
+                                      const SMDS_MeshNode * n25,
+                                      const SMDS_MeshNode * n36)
+{
+  int ID = 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;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
+                                            int n4, int n5, int n6,
+                                            int n12,int n23,int n31,
+                                            int n45,int n56,int n64,
+                                            int n14,int n25,int n36, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((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);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron with 15 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n31,
+                                            const SMDS_MeshNode * n45,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n64,
+                                            const SMDS_MeshNode * n14,
+                                            const SMDS_MeshNode * n25,
+                                            const SMDS_MeshNode * n36,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
+      !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
+    return 0;
+  if(hasConstructionFaces()) {
+    // creation quadratic faces - not implemented
+    return 0;
   }
-
-  myHasInverse = Standard_True;
+  SMDS_QuadraticVolumeOfNodes * volume =
+    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
+                                    n45,n56,n64,n14,n25,n36);
+  myVolumes.Add(volume);
+  myInfo.myNbQuadPrisms++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
 
 
 //=======================================================================
-//function : SubMeshIterator
-//purpose  : returns the ith SubMesh
-//=======================================================================
-
-void SMDS_Mesh::SubMeshIterator(SMDS_ListIteratorOfListOfMesh& itmsh) const
-{
-  itmsh.Initialize(myChildren);
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n67,
+                                      const SMDS_MeshNode * n78,
+                                      const SMDS_MeshNode * n85,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n26,
+                                      const SMDS_MeshNode * n37,
+                                      const SMDS_MeshNode * n48)
+{
+  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;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n5, int n6, int n7, int n8,
+                                            int n12,int n23,int n34,int n41,
+                                            int n56,int n67,int n78,int n85,
+                                            int n15,int n26,int n37,int n48, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((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);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Hexahedrons with 20 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n7,
+                                            const SMDS_MeshNode * n8,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n67,
+                                            const SMDS_MeshNode * n78,
+                                            const SMDS_MeshNode * n85,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n26,
+                                            const SMDS_MeshNode * n37,
+                                            const SMDS_MeshNode * n48,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
+    return 0;
+  if(hasConstructionFaces()) {
+    return 0;
+    // creation quadratic faces - not implemented
+  }
+  SMDS_QuadraticVolumeOfNodes * volume =
+    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8,n12,n23,n34,n41,
+                                    n56,n67,n78,n85,n15,n26,n37,n48);
+  myVolumes.Add(volume);
+  myInfo.myNbQuadHexas++;
+
+  if (!registerElement(ID, volume)) {
+    RemoveElement(volume, false);
+    volume = NULL;
+  }
+  return volume;
 }
-