Salome HOME
0051567: TC6.6.0: Qadrangle_2D fail
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 72aa928c979880a80d2223d13d47b2c3c19dd7f7..fe6f186e496b9b33a9f76da95648fa5b9a0a5598 100644 (file)
@@ -1,23 +1,23 @@
-//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  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
+// 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.
+// 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.
+// 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
+// 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
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 //  SMESH SMDS : implementation of Salome mesh data structure
 #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_FaceOfNodes.hxx"
+#include "SMDS_Mesh.hxx"
 #include "SMDS_PolygonalFaceOfNodes.hxx"
+#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_QuadraticEdge.hxx"
 #include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_QuadraticVolumeOfNodes.hxx"
+#include "SMDS_SetIterator.hxx"
 #include "SMDS_SpacePosition.hxx"
 #include "SMDS_UnstructuredGrid.hxx"
+#include "SMDS_VolumeOfFaces.hxx"
+#include "SMDS_VolumeOfNodes.hxx"
+
+#include "utilities.h"
 
 #include <vtkUnstructuredGrid.h>
 #include <vtkUnstructuredGridWriter.h>
@@ -58,7 +60,7 @@ using namespace std;
 #endif
 
 // number of added entities to check memory after
-#define CHECKMEMORY_INTERVAL 1000
+#define CHECKMEMORY_INTERVAL 100000
 
 vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
 int SMDS_Mesh::chunkSize = 1024;
@@ -80,35 +82,38 @@ int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
   if ( err )
     return -1;
 
+  const unsigned long Mbyte = 1024 * 1024;
+
   static int limit = -1;
   if ( limit < 0 ) {
     int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
     if (status >= 0 ) {
       limit = WEXITSTATUS(status);
     }
+    else {
+      double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
+      limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
+    }
     if ( limit < 20 )
       limit = 20;
     else
-      limit = int( limit * 1.5 );
-#ifdef _DEBUG_
+      limit = int ( limit * 1.5 );
     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
-#endif
   }
 
-  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;
+  //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
 
   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;
@@ -125,7 +130,7 @@ SMDS_Mesh::SMDS_Mesh()
          myHasConstructionEdges(false), myHasConstructionFaces(false),
          myHasInverseElements(true),
          myNodeMin(0), myNodeMax(0),
-         myNodePool(0), myEdgePool(0), myFacePool(0), myVolumePool(0),
+         myNodePool(0), myEdgePool(0), myFacePool(0), myVolumePool(0),myBallPool(0),
          myModified(false), myModifTime(0), myCompactTime(0),
          xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
 {
@@ -144,6 +149,7 @@ SMDS_Mesh::SMDS_Mesh()
   myEdgePool = new ObjectPool<SMDS_VtkEdge>(SMDS_Mesh::chunkSize);
   myFacePool = new ObjectPool<SMDS_VtkFace>(SMDS_Mesh::chunkSize);
   myVolumePool = new ObjectPool<SMDS_VtkVolume>(SMDS_Mesh::chunkSize);
+  myBallPool = new ObjectPool<SMDS_BallElement>(SMDS_Mesh::chunkSize);
 
   myNodes.clear();
   myCells.clear();
@@ -177,7 +183,8 @@ SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
          myNodePool(parent->myNodePool),
          myEdgePool(parent->myEdgePool),
          myFacePool(parent->myFacePool),
-         myVolumePool(parent->myVolumePool)
+         myVolumePool(parent->myVolumePool),
+         myBallPool(parent->myBallPool)
 {
 }
 
@@ -225,7 +232,7 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
     if (ID >= myNodes.size())
     {
         myNodes.resize(ID+SMDS_Mesh::chunkSize, 0);
-        MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
+//         MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
     }
     myNodes[ID] = node;
     myNodeIDFactory->BindID(ID,node);
@@ -268,7 +275,7 @@ SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int I
 {
   if (!n) return 0;
 
-  //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+  if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
   //MESSAGE("Add0DElementWithID" << ID)
   SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
   if (myElementIDFactory->BindID(ID, el0d)) {
@@ -284,6 +291,54 @@ SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int I
   return NULL;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(int idnode, double diameter, int ID)
+{
+  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  if (!node) return NULL;
+  return SMDS_Mesh::AddBallWithID(node, diameter, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
+{
+  return SMDS_Mesh::AddBallWithID(node, diameter, myElementIDFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Ball and at it to the mesh
+/// @param idnode ID of the node
+//  @param diameter ball diameter
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
+{
+  if (!n) return 0;
+
+  if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+  SMDS_BallElement *ball = myBallPool->getNew();
+  ball->init(n->getVtkId(), diameter, this);
+  if (!this->registerElement(ID,ball))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
+      myBallPool->destroy(ball);
+      return 0;
+    }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = ball;
+  myInfo.myNbBalls++;
+  return ball;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// create a MeshEdge and add it to the current Mesh
 /// @return : The created MeshEdge
@@ -475,7 +530,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
     return NULL;
   if ( !e1 || !e2 || !e3 ) return 0;
 
-  //if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   MESSAGE("AddFaceWithID" << ID);
 
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
@@ -521,7 +576,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
     return NULL;
   MESSAGE("AddFaceWithID" << ID);
   if ( !e1 || !e2 || !e3 || !e4 ) return 0;
-  //if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
   adjustmyCellsCapacity(ID);
   myCells[ID] = face;
@@ -591,7 +646,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4) return volume;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
@@ -698,7 +753,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
@@ -810,7 +865,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
@@ -858,6 +913,137 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   return volume;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8,
+                                      const SMDS_MeshNode * n9,
+                                      const SMDS_MeshNode * n10,
+                                      const SMDS_MeshNode * n11,
+                                      const SMDS_MeshNode * n12)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+                                                   n7, n8, n9, n10, n11, n12,
+                                                   ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int idnode9,
+                                             int idnode10,
+                                             int idnode11,
+                                             int idnode12,
+                                             int ID)
+{
+  SMDS_MeshNode *node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
+  SMDS_MeshNode *node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
+  SMDS_MeshNode *node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
+  SMDS_MeshNode *node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
+  SMDS_MeshNode *node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
+  SMDS_MeshNode *node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
+  SMDS_MeshNode *node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
+  SMDS_MeshNode *node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
+  SMDS_MeshNode *node9 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode9);
+  SMDS_MeshNode *node10 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode10);
+  SMDS_MeshNode *node11 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode11);
+  SMDS_MeshNode *node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode12);
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+                                    node7, node8, node9, node10, node11, node12,
+                                    ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n7,
+                                            const SMDS_MeshNode * n8,
+                                            const SMDS_MeshNode * n9,
+                                            const SMDS_MeshNode * n10,
+                                            const SMDS_MeshNode * n11,
+                                            const SMDS_MeshNode * n12,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
+     !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
+    return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionFaces()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else if(hasConstructionEdges()) {
+    MESSAGE("Error : Not implemented");
+    return NULL;
+  }
+  else {
+    // --- retrieve nodes ID
+    vector<vtkIdType> nodeIds;
+    nodeIds.push_back(n1->getVtkId());
+    nodeIds.push_back(n6->getVtkId());
+    nodeIds.push_back(n5->getVtkId());
+    nodeIds.push_back(n4->getVtkId());
+    nodeIds.push_back(n3->getVtkId());
+    nodeIds.push_back(n2->getVtkId());
+
+    nodeIds.push_back(n7->getVtkId());
+    nodeIds.push_back(n12->getVtkId());
+    nodeIds.push_back(n11->getVtkId());
+    nodeIds.push_back(n10->getVtkId());
+    nodeIds.push_back(n9->getVtkId());
+    nodeIds.push_back(n8->getVtkId());
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(nodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+      {
+        this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+        myVolumePool->destroy(volvtk);
+        return 0;
+      }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbHexPrism++;
+  }
+
+  return volume;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 ///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.
@@ -874,7 +1060,6 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                       const SMDS_MeshNode * n8)
 {
   int ID = myElementIDFactory->GetFreeID();
-     //MESSAGE("AddVolumeWithID " << ID);
  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
   if(v==NULL) myElementIDFactory->ReleaseID(ID);
   return v;
@@ -935,7 +1120,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     //MESSAGE("AddVolumeWithID " << ID);
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
@@ -1018,7 +1203,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4) return 0;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
   adjustmyCellsCapacity(ID);
   myCells[ID] = volume;
@@ -1066,7 +1251,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
   adjustmyCellsCapacity(ID);
   myCells[ID] = volume;
@@ -1116,7 +1301,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
   adjustmyCellsCapacity(ID);
   myCells[ID] = volume;
@@ -1134,8 +1319,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
 /// Add a polygon defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (vector<int> nodes_ids,
-                                                  const int        ID)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
+                                                  const int           ID)
 {
   int nbNodes = nodes_ids.size();
   vector<const SMDS_MeshNode*> nodes (nbNodes);
@@ -1151,12 +1336,12 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (vector<int> nodes_ids,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
-                          (vector<const SMDS_MeshNode*> nodes,
-                           const int                         ID)
+                          (const vector<const SMDS_MeshNode*> & nodes,
+                           const int                            ID)
 {
   SMDS_MeshFace * face;
 
-  //if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if (hasConstructionEdges())
     {
       MESSAGE("Error : Not implemented");
@@ -1168,7 +1353,7 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
     //MESSAGE("AddPolygonalFaceWithID vtk " << ID);
     vector<vtkIdType> nodeIds;
     nodeIds.clear();
-    vector<const SMDS_MeshNode*>::iterator it = nodes.begin();
+    vector<const SMDS_MeshNode*>::const_iterator it = nodes.begin();
     for ( ; it != nodes.end(); ++it)
       nodeIds.push_back((*it)->getVtkId());
 
@@ -1208,7 +1393,7 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
 /// An ID is automatically affected to the created face.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (vector<const SMDS_MeshNode*> nodes)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
 {
   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
 }
@@ -1221,9 +1406,9 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (vector<const SMDS_MeshNode*> nodes)
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
-                             (vector<int> nodes_ids,
-                              vector<int> quantities,
-                              const int        ID)
+                             (const vector<int> & nodes_ids,
+                              const vector<int> & quantities,
+                              const int           ID)
 {
   int nbNodes = nodes_ids.size();
   vector<const SMDS_MeshNode*> nodes (nbNodes);
@@ -1241,12 +1426,14 @@ SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
-                            (vector<const SMDS_MeshNode*> nodes,
-                             vector<int>                  quantities,
-                             const int                    ID)
+                            (const vector<const SMDS_MeshNode*>& nodes,
+                             const vector<int>                 & quantities,
+                             const int                           ID)
 {
-  SMDS_MeshVolume* volume;
-  //if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  SMDS_MeshVolume* volume = 0;
+  if ( nodes.empty() || quantities.empty() )
+    return NULL;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if (hasConstructionFaces())
     {
       MESSAGE("Error : Not implemented");
@@ -1263,7 +1450,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
       //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID);
       vector<vtkIdType> nodeIds;
       nodeIds.clear();
-      vector<const SMDS_MeshNode*>::iterator it = nodes.begin();
+      vector<const SMDS_MeshNode*>::const_iterator it = nodes.begin();
       for (; it != nodes.end(); ++it)
         nodeIds.push_back((*it)->getVtkId());
 
@@ -1304,8 +1491,8 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
-                            (vector<const SMDS_MeshNode*> nodes,
-                             vector<int>                  quantities)
+                            (const vector<const SMDS_MeshNode*> & nodes,
+                             const vector<int>                  & quantities)
 {
   int ID = myElementIDFactory->GetFreeID();
   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
@@ -1372,6 +1559,53 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIdsWithID(const std::vector<vtkIdTyp
   return volvtk;
 }
 
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshFace * f = SMDS_Mesh::AddFaceFromVtkIdsWithID(vtkNodeIds, ID);
+  if (f == NULL) myElementIDFactory->ReleaseID(ID);
+  return f;
+}
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
+{
+  SMDS_VtkFace *facevtk = myFacePool->getNew();
+  facevtk->init(vtkNodeIds, this);
+  if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = facevtk;
+  vtkIdType aVtkType = facevtk->GetVtkType();
+  switch (aVtkType)
+  {
+    case VTK_TRIANGLE:
+      myInfo.myNbTriangles++;
+      break;
+    case VTK_QUAD:
+      myInfo.myNbQuadrangles++;
+      break;
+    case VTK_QUADRATIC_TRIANGLE:
+      myInfo.myNbQuadTriangles++;
+      break;
+    case VTK_QUADRATIC_QUAD:
+      myInfo.myNbQuadQuadrangles++;
+      break;
+    case VTK_BIQUADRATIC_QUAD:
+      myInfo.myNbBiQuadQuadrangles++;
+      break;
+    case VTK_POLYGON:
+      myInfo.myNbPolygons++;
+      break;
+     default:
+      myInfo.myNbPolygons++;
+  }
+  return facevtk;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// Registers element with the given ID, maintains inverse connections
 ///////////////////////////////////////////////////////////////////////////////
@@ -1395,7 +1629,7 @@ bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element)
 
   if (vtkId >= myCellIdVtkToSmds.size()) // --- resize local vector
   {
-    MESSAGE(" --------------------- resize myCellIdVtkToSmds " << vtkId << " --> " << vtkId + SMDS_Mesh::chunkSize);
+//     MESSAGE(" --------------------- resize myCellIdVtkToSmds " << vtkId << " --> " << vtkId + SMDS_Mesh::chunkSize);
     myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1);
   }
   myCellIdVtkToSmds[vtkId] = ID;
@@ -1411,9 +1645,9 @@ const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
 {
   if (ID < 1 || ID >= myNodes.size())
   {
-    MESSAGE("------------------------------------------------------------------------- ");
-    MESSAGE("----------------------------------- bad ID " << ID << " " << myNodes.size());
-    MESSAGE("------------------------------------------------------------------------- ");
+//     MESSAGE("------------------------------------------------------------------------- ");
+//     MESSAGE("----------------------------------- bad ID " << ID << " " << myNodes.size());
+//     MESSAGE("------------------------------------------------------------------------- ");
     return 0;
   }
   return (const SMDS_MeshNode *)myNodes[ID];
@@ -1445,7 +1679,7 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
                                           int ID)
 {
   if ( !node1 || !node2 || !node3) return 0;
-//  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionEdges())
   {
     SMDS_MeshEdge *edge1, *edge2, *edge3;
@@ -1498,7 +1732,7 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
                                             int ID)
 {
   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
-//  if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionEdges())
   {
       //MESSAGE("createQuadrangle hasConstructionEdges "<< ID);
@@ -1636,10 +1870,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
 {
   MESSAGE("SMDS_Mesh::ChangeElementNodes");
   // keep current nodes of elem
-  set<const SMDS_MeshElement*> oldNodes;
-  SMDS_ElemIteratorPtr itn = element->nodesIterator();
-  while(itn->more())
-    oldNodes.insert(itn->next());
+  set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
 
   // change nodes
   bool Ok = false;
@@ -1652,7 +1883,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
 
   if ( Ok ) { // update InverseElements
 
-    set<const SMDS_MeshElement*>::iterator it;
+    set<const SMDS_MeshNode*>::iterator it;
 
     // AddInverseElement to new nodes
     for ( int i = 0; i < nbnodes; i++ ) {
@@ -1667,8 +1898,7 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
     // RemoveInverseElement from the nodes removed from elem
     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
     {
-      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
-        (const_cast<SMDS_MeshElement *>( *it ));
+      SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
       n->RemoveInverseElement( cell );
     }
   }
@@ -1761,6 +1991,31 @@ const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
   return toReturn;
 }
 
+//=======================================================================
+//function : FindBall
+//purpose  :
+//=======================================================================
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
+{
+  const SMDS_MeshNode * node = FindNode(idnode);
+  if(node == NULL) return NULL;
+  return FindBall(node);
+}
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
+{
+  if (!node) return 0;
+  const SMDS_BallElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->GetGeomType() == SMDSGeom_BALL)
+      toReturn = static_cast<const SMDS_BallElement*>(e);
+  }
+  return toReturn;
+}
+
 //=======================================================================
 //function : Find0DElementOrCreate
 //purpose  :
@@ -1828,7 +2083,7 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
   SMDS_MeshEdge * toReturn=NULL;
   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
   if(toReturn==NULL) {
-    //if ( myEdges.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+    if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
     int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
     adjustmyCellsCapacity(ID);
     vector<vtkIdType> nodeIds;
@@ -2217,7 +2472,7 @@ void SMDS_Mesh::DumpNodes() const
 void SMDS_Mesh::Dump0DElements() const
 {
   MESSAGE("dump 0D elements of mesh : ");
-  SMDS_0DElementIteratorPtr it0d = elements0dIterator();
+  SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
   while(it0d->more()) ; //MESSAGE(it0d->next());
 }
 
@@ -2323,7 +2578,15 @@ int SMDS_Mesh::NbNodes() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::Nb0DElements() const
 {
-  return myInfo.Nb0DElements(); // -PR- a verfier
+  return myInfo.Nb0DElements();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbBalls() const
+{
+  return myInfo.NbBalls();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2331,7 +2594,7 @@ int SMDS_Mesh::Nb0DElements() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbEdges() const
 {
-        return myInfo.NbEdges(); // -PR- a verfier
+  return myInfo.NbEdges();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2339,7 +2602,7 @@ int SMDS_Mesh::NbEdges() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbFaces() const
 {
-        return myInfo.NbFaces();  // -PR- a verfier
+  return myInfo.NbFaces();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2347,17 +2610,16 @@ int SMDS_Mesh::NbFaces() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbVolumes() const
 {
-        return myInfo.NbVolumes(); // -PR- a verfier
+  return myInfo.NbVolumes();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return the number of child mesh of this mesh.
-/// Note that the tree structure of SMDS_Mesh seems to be unused in this version
-/// (2003-09-08) of SMESH
+/// Note that the tree structure of SMDS_Mesh is unused in SMESH
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbSubMesh() const
 {
-        return myChildren.size();
+  return myChildren.size();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2394,38 +2656,6 @@ SMDS_Mesh::~SMDS_Mesh()
         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
       }
   }
-
-//   SetOfNodes::Iterator itn(myNodes);
-//   for (; itn.More(); itn.Next())
-//     delete itn.Value();
-
-//   SetOf0DElements::Iterator it0d (my0DElements);
-//   for (; it0d.More(); it0d.Next())
-//   {
-//     SMDS_MeshElement* elem = it0d.Value();
-//     delete elem;
-//   }
-
-//   SetOfEdges::Iterator ite(myEdges);
-//   for (; ite.More(); ite.Next())
-//   {
-//     SMDS_MeshElement* elem = ite.Value();
-//     delete elem;
-//   }
-
-//   SetOfFaces::Iterator itf(myFaces);
-//   for (; itf.More(); itf.Next())
-//   {
-//     SMDS_MeshElement* elem = itf.Value();
-//     delete elem;
-//   }
-
-//   SetOfVolumes::Iterator itv(myVolumes);
-//   for (; itv.More(); itv.Next())
-//   {
-//     SMDS_MeshElement* elem = itv.Value();
-//     delete elem;
-//   }
 }
 
 //================================================================================
@@ -2477,6 +2707,9 @@ void SMDS_Mesh::Clear()
         case SMDSAbs_Volume:
           myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
           break;
+        case SMDSAbs_Ball:
+          myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
+          break;
         default:
           break;
       }
@@ -2578,78 +2811,7 @@ void SMDS_Mesh::setInverseElements(bool b)
 
 namespace {
 
-///////////////////////////////////////////////////////////////////////////////
-///Iterator on NCollection_Map
-///////////////////////////////////////////////////////////////////////////////
-template <class MAP, typename ELEM=const SMDS_MeshElement*, class FATHER=SMDS_ElemIterator>
-struct MYNode_Map_Iterator: public FATHER
-{
-  int _ctr;
-  const MAP& _map;
-  MYNode_Map_Iterator(const MAP& map): _map(map) // map is a std::vector<ELEM>
-  {
-      _ctr = 0;
-  }
-
-  bool more()
-  {
-      while (_ctr < _map.size())
-      {
-          if (_map[_ctr])
-              return true;
-          _ctr++;
-      }
-          return false;
-  }
-
-  ELEM next()
-  {
-    ELEM current = _map[_ctr];
-    _ctr++;
-    return current;
-  }
-};
-
-template <class MAP, typename ELEM=const SMDS_MeshElement*, class FATHER=SMDS_ElemIterator>
-struct MYElem_Map_Iterator: public FATHER
-{
-  int _ctr;
-  int _type;
-  const MAP& _map;
-  MYElem_Map_Iterator(const MAP& map, int typ): _map(map) // map is a std::vector<ELEM>
-  {
-      _ctr = 0;
-      _type = typ;
-      while (_ctr < _map.size()) // go to the first valid element
-      {
-          if (_map[_ctr])
-            if ( (_type == SMDSAbs_All) || (_map[_ctr]->GetType() == _type))
-              break;
-          _ctr++;
-      }
-  }
-
-bool more()
-  {
-      while (_ctr < _map.size())
-      {
-          if (_map[_ctr])
-            if ( (_type == SMDSAbs_All) || (_map[_ctr]->GetType() == _type))
-              return true;
-          _ctr++;
-      }
-          return false;
-  }
-
-  ELEM next()
-  {
-    ELEM current = dynamic_cast<ELEM> (_map[_ctr]);
-    _ctr++;
-    return current;
-  }
-};
-
-//================================================================================
+  //================================================================================
   /*!
    * \brief Iterator on elements in id increasing order
    */
@@ -2658,7 +2820,7 @@ bool more()
   template <typename ELEM=const SMDS_MeshElement*>
   class IdSortedIterator : public SMDS_Iterator<ELEM>
   {
-    const SMDS_MeshElementIDFactory& myIDFact;
+    SMDS_MeshElementIDFactory&       myIDFact;
     int                              myID, myMaxID, myNbFound, myTotalNb;
     SMDSAbs_ElementType              myType;
     ELEM                             myElem;
@@ -2692,6 +2854,44 @@ bool more()
       return current;
     }
   };
+
+  //================================================================================
+  /*!
+   * \brief Iterator on vector of elements, possibly being resized while iteration
+   */
+  //================================================================================
+
+  template<typename RETURN_VALUE,
+           typename VECTOR_VALUE=SMDS_MeshCell*,
+           typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
+  class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
+  {
+    const std::vector<VECTOR_VALUE>& _vector;
+    size_t                           _index;
+    bool                             _more;
+    VALUE_FILTER                     _filter;
+  public:
+    ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
+                    const VALUE_FILTER&              filter=VALUE_FILTER() )
+      :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
+    {
+      if ( _more && !_filter( _vector[ _index ]))
+        next();
+    }
+    virtual bool more()
+    {
+      return _more;
+    }
+    virtual RETURN_VALUE next()
+    {
+      if ( !_more ) return NULL;
+      VECTOR_VALUE current = _vector[ _index ];
+      _more = 0;
+      while ( !_more && ++_index < _vector.size() )
+        _more = _filter( _vector[ _index ]);
+      return (RETURN_VALUE) current;
+    }
+  };
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2700,34 +2900,50 @@ bool more()
 
 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
 {
-  typedef MYNode_Map_Iterator
-    < SetOfNodes, const SMDS_MeshNode*, SMDS_NodeIterator > TIterator;
-  return SMDS_NodeIteratorPtr( new TIterator(myNodes)); // naturally always sorted by ID
+  // naturally always sorted by ID
+  typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
+  return SMDS_NodeIteratorPtr( new TIterator(myNodes));
+}
 
-//  typedef IdSortedIterator< const SMDS_MeshNode* >          TSortedIterator;
-//  return ( idInceasingOrder ?
-//           SMDS_NodeIteratorPtr( new TSortedIterator( *myNodeIDFactory, SMDSAbs_Node, NbNodes())) :
-//           SMDS_NodeIteratorPtr( new TIterator(myNodes)));
+SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
+{
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
+  return SMDS_ElemIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
 }
 
-///////////////////////////////////////////////////////////////////////////////
-///Return an iterator on 0D elements of the current mesh.
-///////////////////////////////////////////////////////////////////////////////
+SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
+{
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
+  return SMDS_ElemIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
+}
 
-SMDS_0DElementIteratorPtr SMDS_Mesh::elements0dIterator(bool idInceasingOrder) const
+///////////////////////////////////////////////////////////////////////////////
+/// Return an iterator on elements of the current mesh factory
+///////////////////////////////////////////////////////////////////////////////
+SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 {
-  typedef MYElem_Map_Iterator
-    < SetOfCells, const SMDS_Mesh0DElement*, SMDS_0DElementIterator > TIterator;
-  return SMDS_0DElementIteratorPtr(new TIterator(myCells, SMDSAbs_0DElement)); // naturally always sorted by ID
+  // naturally always sorted by ID
+  switch ( type ) {
+
+  case SMDSAbs_All:
+    return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
 
-//  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)));
+  case SMDSAbs_Node:
+    return SMDS_ElemIteratorPtr
+      ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
+
+  default:
+    typedef ElemVecIterator
+      < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+    return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
+  }
+  return SMDS_ElemIteratorPtr();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2736,18 +2952,11 @@ SMDS_0DElementIteratorPtr SMDS_Mesh::elements0dIterator(bool idInceasingOrder) c
 
 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
 {
-  typedef MYElem_Map_Iterator
-    < SetOfCells, const SMDS_MeshEdge*, SMDS_EdgeIterator > TIterator;
-  return SMDS_EdgeIteratorPtr(new TIterator(myCells, SMDSAbs_Edge)); // naturally always sorted by ID
-
-//  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)));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_EdgeIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2756,18 +2965,11 @@ SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
 
 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
 {
-  typedef MYElem_Map_Iterator
-    < SetOfCells, const SMDS_MeshFace*, SMDS_FaceIterator > TIterator;
-  return SMDS_FaceIteratorPtr(new TIterator(myCells, SMDSAbs_Face)); // naturally always sorted by ID
-
-//  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)));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_FaceIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2776,43 +2978,11 @@ SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
 
 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
 {
-  typedef MYElem_Map_Iterator
-    < SetOfCells, const SMDS_MeshVolume*, SMDS_VolumeIterator > TIterator;
-  return SMDS_VolumeIteratorPtr(new TIterator(myCells, SMDSAbs_Volume)); // naturally always sorted by ID
-
-  //  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:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfCells >(myCells, SMDSAbs_All));
-    break;
-  case SMDSAbs_Volume:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfCells >(myCells, SMDSAbs_Volume));
-  case SMDSAbs_Face:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfCells >(myCells, SMDSAbs_Face));
-  case SMDSAbs_Edge:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfCells >(myCells, SMDSAbs_Edge));
-  case SMDSAbs_0DElement:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfCells >(myCells, SMDSAbs_0DElement));
-  case SMDSAbs_Node:
-    return SMDS_ElemIteratorPtr (new MYElem_Map_Iterator< SetOfNodes >(myNodes, SMDSAbs_All));
-    //return myNodeIDFactory->elementsIterator();
-  default:;
-  }
-  return myElementIDFactory->elementsIterator();
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_VolumeIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2869,7 +3039,7 @@ static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement *
                 i++;
         }
         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
-        MESSAGE("nb elems " << i << " intersection " << retSet->size());
+//         MESSAGE("nb elems " << i << " intersection " << retSet->size());
         delete [] initSet;
         return retSet;
 }
@@ -3101,6 +3271,19 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
           else
             delete (*it);
           break;
+        case SMDSAbs_Ball:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0;
+              myInfo.remove(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
+            myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
+          else
+            delete (*it);
+          break;
       }
       if (vtkid >= 0)
         {
@@ -3199,6 +3382,11 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
       myInfo.RemoveVolume(elem);
       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
       break;
+    case SMDSAbs_Ball:
+      myCells[elemId] = 0;
+      myInfo.remove(elem);
+      myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
+      break;
     default:
       break;
     }
@@ -3221,22 +3409,10 @@ bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
   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();
+  SMDS_ElemIteratorPtr ite = elementsIterator();
   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;
 }
 
@@ -3592,6 +3768,101 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   }
 }
 
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n34,
+                                  const SMDS_MeshNode * n41,
+                                  const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
+                                  myElementIDFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
+                                        int n12,int n23,int n34,int n41, int nCenter, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID
+    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
+     ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
+                                        const SMDS_MeshNode * nCenter,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
+  if(hasConstructionEdges()) {
+    // creation quadratic edges - not implemented
+        return 0;
+  }
+  else
+  {
+    // --- retrieve nodes ID
+    vector<vtkIdType> nodeIds;
+    nodeIds.clear();
+    nodeIds.push_back(n1->getVtkId());
+    nodeIds.push_back(n2->getVtkId());
+    nodeIds.push_back(n3->getVtkId());
+    nodeIds.push_back(n4->getVtkId());
+    nodeIds.push_back(n12->getVtkId());
+    nodeIds.push_back(n23->getVtkId());
+    nodeIds.push_back(n34->getVtkId());
+    nodeIds.push_back(n41->getVtkId());
+    nodeIds.push_back(nCenter->getVtkId());
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(nodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+      {
+        this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+        myFacePool->destroy(facevtk);
+        return 0;
+      }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbBiQuadQuadrangles++;
+
+//    if (!registerElement(ID, face)) {
+//      RemoveElement(face, false);
+//      face = NULL;
+//    }
+    return face;
+  }
+}
+
 
 //=======================================================================
 //function : AddVolume
@@ -4086,6 +4357,184 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   return volvtk;
 }
 
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n67,
+                                      const SMDS_MeshNode * n78,
+                                      const SMDS_MeshNode * n85,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n26,
+                                      const SMDS_MeshNode * n37,
+                                      const SMDS_MeshNode * n48,
+                                      const SMDS_MeshNode * n1234,
+                                      const SMDS_MeshNode * n1256,
+                                      const SMDS_MeshNode * n2367,
+                                      const SMDS_MeshNode * n3478,
+                                      const SMDS_MeshNode * n1458,
+                                      const SMDS_MeshNode * n5678,
+                                      const SMDS_MeshNode * nCenter)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v =
+    SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
+                               n56, n67, n78, n85, n15, n26, n37, n48,
+                               n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
+                               ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n5, int n6, int n7, int n8,
+                                            int n12,int n23,int n34,int n41,
+                                            int n56,int n67,int n78,int n85,
+                                            int n15,int n26,int n37,int n48,
+                                            int n1234,int n1256,int n2367,int n3478,
+                                            int n1458,int n5678,int nCenter, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
+     ID);
+}
+
+//=======================================================================
+//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,
+                                            const SMDS_MeshNode * n1234,
+                                            const SMDS_MeshNode * n1256,
+                                            const SMDS_MeshNode * n2367,
+                                            const SMDS_MeshNode * n3478,
+                                            const SMDS_MeshNode * n1458,
+                                            const SMDS_MeshNode * n5678,
+                                            const SMDS_MeshNode * nCenter,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
+      !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
+    return 0;
+  if(hasConstructionFaces()) {
+    return 0;
+    // creation quadratic faces - not implemented
+  }
+  // --- retrieve nodes ID
+  vector<vtkIdType> nodeIds;
+  nodeIds.clear();
+  nodeIds.push_back(n1->getVtkId());
+  nodeIds.push_back(n4->getVtkId());
+  nodeIds.push_back(n3->getVtkId());
+  nodeIds.push_back(n2->getVtkId());
+
+  nodeIds.push_back(n5->getVtkId());
+  nodeIds.push_back(n8->getVtkId());
+  nodeIds.push_back(n7->getVtkId());
+  nodeIds.push_back(n6->getVtkId());
+
+  nodeIds.push_back(n41->getVtkId());
+  nodeIds.push_back(n34->getVtkId());
+  nodeIds.push_back(n23->getVtkId());
+  nodeIds.push_back(n12->getVtkId());
+
+  nodeIds.push_back(n85->getVtkId());
+  nodeIds.push_back(n78->getVtkId());
+  nodeIds.push_back(n67->getVtkId());
+  nodeIds.push_back(n56->getVtkId());
+
+  nodeIds.push_back(n15->getVtkId());
+  nodeIds.push_back(n48->getVtkId());
+  nodeIds.push_back(n37->getVtkId());
+  nodeIds.push_back(n26->getVtkId());
+
+  nodeIds.push_back(n1256->getVtkId());
+  nodeIds.push_back(n3478->getVtkId());
+  nodeIds.push_back(n1458->getVtkId());
+  nodeIds.push_back(n2367->getVtkId());
+  nodeIds.push_back(n1234->getVtkId());
+  nodeIds.push_back(n5678->getVtkId());
+  nodeIds.push_back(nCenter->getVtkId());
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(nodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbTriQuadHexas++;
+
+  return volvtk;
+}
+
+
 void SMDS_Mesh::updateNodeMinMax()
 {
   myNodeMin = 0;
@@ -4234,7 +4683,7 @@ void SMDS_Mesh::Modified()
 }
 
 //! get last modification timeStamp
-unsigned long SMDS_Mesh::GetMTime()
+unsigned long SMDS_Mesh::GetMTime() const
 {
   return this->myModifTime;
 }