Salome HOME
IPAL54382: TC8.5.0: SMESH: Regression in mesh visualization (body fitting)
[modules/smesh.git] / src / SMESHDS / SMESHDS_Mesh.cxx
index 885a76107185f07d7b76209a5139f64335f1d292..7a8714424974831a8fe72e7c73b9aa4a7041c9aa 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 //
 #include "SMESHDS_Mesh.hxx"
 
-#include "SMESHDS_Group.hxx"
-#include "SMDS_VertexPosition.hxx"
+#include "SMDS_Downward.hxx"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
-#include "SMDS_Downward.hxx"
+#include "SMDS_VertexPosition.hxx"
+#include "SMESHDS_Group.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
 #include "SMESHDS_Script.hxx"
+#include "SMESHDS_TSubMeshHolder.hxx"
 
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_OutOfRange.hxx>
@@ -49,7 +50,9 @@
 
 #include "utilities.h"
 
-using namespace std;
+class SMESHDS_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< const SMESHDS_SubMesh >
+{
+};
 
 //=======================================================================
 //function : Create
@@ -57,11 +60,10 @@ using namespace std;
 //=======================================================================
 SMESHDS_Mesh::SMESHDS_Mesh(int theMeshID, bool theIsEmbeddedMode):
   myMeshID(theMeshID),
-  myIsEmbeddedMode(theIsEmbeddedMode),
-  myCurSubID(-1)
+  mySubMeshHolder( new SubMeshHolder ),
+  myIsEmbeddedMode(theIsEmbeddedMode)
 {
   myScript = new SMESHDS_Script(theIsEmbeddedMode);
-  myCurSubMesh = 0;
   SetPersistentId(theMeshID);
 }
 
@@ -101,28 +103,26 @@ int SMESHDS_Mesh::GetPersistentId() const
 //=======================================================================
 void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
 {
-  if ( !myShape.IsNull() && S.IsNull() )
+  if ( !myShape.IsNull() && S.IsNull() ) // case: "save study" after geometry removal
   {
     // removal of a shape to mesh, delete ...
     // - hypotheses
     myShapeToHypothesis.Clear();
     // - shape indices in SMDS_Position of nodes
-    map<int,SMESHDS_SubMesh*>::iterator i_sub = myShapeIndexToSubMesh.begin();
-    for ( ; i_sub != myShapeIndexToSubMesh.end(); i_sub++ ) {
-      if ( !i_sub->second->IsComplexSubmesh() ) {
-        SMDS_NodeIteratorPtr nIt = i_sub->second->GetNodes();
+    SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+    while ( SMESHDS_SubMesh* sm = const_cast< SMESHDS_SubMesh* >( smIt->next() )) {
+      if ( !sm->IsComplexSubmesh() ) {
+        SMDS_NodeIteratorPtr nIt = sm->GetNodes();
         while ( nIt->more() )
-          i_sub->second->RemoveNode(nIt->next(), false);
+          sm->RemoveNode(nIt->next());
       }
     }
     // - sub-meshes
-    TShapeIndexToSubMesh::iterator i_sm = myShapeIndexToSubMesh.begin();
-    for ( ; i_sm != myShapeIndexToSubMesh.end(); ++i_sm )
-      delete i_sm->second;
-    myShapeIndexToSubMesh.clear();
+    mySubMeshHolder->DeleteAll();
+
     myIndexToShape.Clear();
     // - groups on geometry
-    set<SMESHDS_GroupBase*>::iterator gr = myGroups.begin();
+    std::set<SMESHDS_GroupBase*>::iterator gr = myGroups.begin();
     while ( gr != myGroups.end() ) {
       if ( dynamic_cast<SMESHDS_GroupOnGeom*>( *gr ))
         myGroups.erase( gr++ );
@@ -135,6 +135,8 @@ void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
     if ( !S.IsNull() )
       TopExp::MapShapes(myShape, myIndexToShape);
   }
+
+  SMDS_Mesh::setNbShapes( MaxShapeIndex() );
 }
 
 //=======================================================================
@@ -145,15 +147,15 @@ void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
 bool SMESHDS_Mesh::AddHypothesis(const TopoDS_Shape & SS,
                                  const SMESHDS_Hypothesis * H)
 {
-  if (!myShapeToHypothesis.IsBound(SS.Oriented(TopAbs_FORWARD))) {
-    list<const SMESHDS_Hypothesis *> aList;
-    myShapeToHypothesis.Bind(SS.Oriented(TopAbs_FORWARD), aList);
+  if (!myShapeToHypothesis.IsBound(SS/*.Oriented(TopAbs_FORWARD)*/)) {
+    std::list<const SMESHDS_Hypothesis *> aList;
+    myShapeToHypothesis.Bind(SS/*.Oriented(TopAbs_FORWARD)*/, aList);
   }
-  list<const SMESHDS_Hypothesis *>& alist =
-    myShapeToHypothesis(SS.Oriented(TopAbs_FORWARD)); // ignore orientation of SS
+  std::list<const SMESHDS_Hypothesis *>& alist =
+    myShapeToHypothesis(SS/*.Oriented(TopAbs_FORWARD)*/); // ignore orientation of SS
 
   //Check if the Hypothesis is still present
-  list<const SMESHDS_Hypothesis*>::iterator ith = find(alist.begin(),alist.end(), H );
+  std::list<const SMESHDS_Hypothesis*>::iterator ith = find(alist.begin(),alist.end(), H );
 
   if (alist.end() != ith) return false;
 
@@ -169,10 +171,10 @@ bool SMESHDS_Mesh::AddHypothesis(const TopoDS_Shape & SS,
 bool SMESHDS_Mesh::RemoveHypothesis(const TopoDS_Shape &       S,
                                     const SMESHDS_Hypothesis * H)
 {
-  if( myShapeToHypothesis.IsBound( S.Oriented(TopAbs_FORWARD) ) )
+  if( myShapeToHypothesis.IsBound( S/*.Oriented(TopAbs_FORWARD)*/ ) )
   {
-    list<const SMESHDS_Hypothesis *>& alist=myShapeToHypothesis.ChangeFind( S.Oriented(TopAbs_FORWARD) );
-    list<const SMESHDS_Hypothesis*>::iterator ith=find(alist.begin(),alist.end(), H );
+    std::list<const SMESHDS_Hypothesis *>& alist=myShapeToHypothesis.ChangeFind( S/*.Oriented(TopAbs_FORWARD)*/ );
+    std::list<const SMESHDS_Hypothesis*>::iterator ith=find(alist.begin(),alist.end(), H );
     if (ith != alist.end())
     {
       alist.erase(ith);
@@ -211,18 +213,17 @@ void SMESHDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z
 
 //=======================================================================
 //function : ChangeElementNodes
-//purpose  : 
+//purpose  : Changed nodes of an element provided that nb of nodes does not change
 //=======================================================================
 
 bool SMESHDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
                                       const SMDS_MeshNode    * nodes[],
                                       const int                nbnodes)
 {
-  //MESSAGE("SMESHDS_Mesh::ChangeElementNodes");
   if ( ! SMDS_Mesh::ChangeElementNodes( elem, nodes, nbnodes ))
     return false;
 
-  vector<int> IDs( nbnodes );
+  std::vector<int> IDs( nbnodes );
   for ( int i = 0; i < nbnodes; i++ )
     IDs [ i ] = nodes[ i ]->GetID();
   myScript->ChangeElementNodes( elem->GetID(), &IDs[0], nbnodes);
@@ -235,8 +236,8 @@ bool SMESHDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
 //purpose  : 
 //=======================================================================
 bool SMESHDS_Mesh::ChangePolygonNodes
-                   (const SMDS_MeshElement *     elem,
                   vector<const SMDS_MeshNode*> nodes)
+(const SMDS_MeshElement *     elem,
std::vector<const SMDS_MeshNode*> nodes)
 {
   ASSERT(nodes.size() > 3);
 
@@ -248,14 +249,14 @@ bool SMESHDS_Mesh::ChangePolygonNodes
 //purpose  : 
 //=======================================================================
 bool SMESHDS_Mesh::ChangePolyhedronNodes
-                   (const SMDS_MeshElement * elem,
                   std::vector<const SMDS_MeshNode*> nodes,
                   std::vector<int>                  quantities)
+(const SMDS_MeshElement * elem,
+ std::vector<const SMDS_MeshNode*> nodes,
+ std::vector<int>                  quantities)
 {
   ASSERT(nodes.size() > 3);
 
-  if (!SMDS_Mesh::ChangePolyhedronNodes(elem, nodes, quantities))
-    return false;
+  //if (!SMDS_Mesh::ChangePolyhedronNodes(elem, nodes, quantities))
+  return false;
 
   int i, len = nodes.size();
   std::vector<int> nodes_ids (len);
@@ -275,10 +276,10 @@ bool SMESHDS_Mesh::ChangePolyhedronNodes
 void SMESHDS_Mesh::Renumber (const bool isNodes, const int startID, const int deltaID)
 {
   // TODO not possible yet to have node numbers not starting to O and continuous.
-  if (!this->isCompacted())
-    this->compactMesh();
-//  SMDS_Mesh::Renumber( isNodes, startID, deltaID );
-//  myScript->Renumber( isNodes, startID, deltaID );
+  if ( !this->IsCompacted() )
+    this->CompactMesh();
+  //  SMDS_Mesh::Renumber( isNodes, startID, deltaID );
+  //  myScript->Renumber( isNodes, startID, deltaID );
 }
 
 //=======================================================================
@@ -293,7 +294,7 @@ SMDS_Mesh0DElement* SMESHDS_Mesh::Add0DElementWithID(int nodeID, int ID)
 }
 
 SMDS_Mesh0DElement* SMESHDS_Mesh::Add0DElementWithID
-                                  (const SMDS_MeshNode * node, int ID)
+(const SMDS_MeshNode * node, int ID)
 {
   return Add0DElementWithID(node->GetID(), ID);
 }
@@ -706,9 +707,9 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID (const std::vector<int>& nod
   return anElem;
 }
 
-SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID
-                             (const std::vector<const SMDS_MeshNode*>& nodes,
-                              const int                                ID)
+SMDS_MeshFace*
+SMESHDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                      const int                                ID)
 {
   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
   if (anElem) {
@@ -722,8 +723,8 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID
   return anElem;
 }
 
-SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFace
-                             (const std::vector<const SMDS_MeshNode*>& nodes)
+SMDS_MeshFace*
+SMESHDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes)
 {
   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFace(nodes);
   if (anElem) {
@@ -737,6 +738,53 @@ SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFace
   return anElem;
 }
 
+
+//=======================================================================
+//function : AddQuadPolygonalFace
+//purpose  : 
+//=======================================================================
+SMDS_MeshFace* SMESHDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int>& nodes_ids,
+                                                         const int               ID)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes_ids, ID);
+  if (anElem) {
+    myScript->AddQuadPolygonalFace(ID, nodes_ids);
+  }
+  return anElem;
+}
+
+SMDS_MeshFace*
+SMESHDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*>& nodes,
+                                          const int                                ID)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
+  if (anElem) {
+    int i, len = nodes.size();
+    std::vector<int> nodes_ids (len);
+    for (i = 0; i < len; i++) {
+      nodes_ids[i] = nodes[i]->GetID();
+    }
+    myScript->AddQuadPolygonalFace(ID, nodes_ids);
+  }
+  return anElem;
+}
+
+SMDS_MeshFace*
+SMESHDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*>& nodes)
+{
+  SMDS_MeshFace *anElem = SMDS_Mesh::AddQuadPolygonalFace(nodes);
+  if (anElem) {
+    int i, len = nodes.size();
+    std::vector<int> nodes_ids (len);
+    for (i = 0; i < len; i++) {
+      nodes_ids[i] = nodes[i]->GetID();
+    }
+    myScript->AddQuadPolygonalFace(anElem->GetID(), nodes_ids);
+  }
+  return anElem;
+}
+
+
 //=======================================================================
 //function : AddPolyhedralVolume
 //purpose  : 
@@ -753,9 +801,9 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int>
 }
 
 SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolumeWithID
-                               (const std::vector<const SMDS_MeshNode*>& nodes,
                               const std::vector<int>&                  quantities,
                               const int                                ID)
+(const std::vector<const SMDS_MeshNode*>& nodes,
+ const std::vector<int>&                  quantities,
+ const int                                ID)
 {
   SMDS_MeshVolume *anElem = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
   if (anElem) {
@@ -770,8 +818,8 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolumeWithID
 }
 
 SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolume
-                               (const std::vector<const SMDS_MeshNode*>& nodes,
                               const std::vector<int>&                  quantities)
+(const std::vector<const SMDS_MeshNode*>& nodes,
+ const std::vector<int>&                  quantities)
 {
   SMDS_MeshVolume *anElem = SMDS_Mesh::AddPolyhedralVolume(nodes, quantities);
   if (anElem) {
@@ -790,10 +838,9 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolume
 //purpose  : 
 //=======================================================================
 
-static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
-                                  set<SMESHDS_GroupBase*>&       theGroups,
-                                  list<const SMDS_MeshElement*>& theElems,
-                                  const bool                     isNode)
+static void removeFromContainers (SMESHDS_Mesh*                         theMesh,
+                                  std::set<SMESHDS_GroupBase*>&         theGroups,
+                                  std::vector<const SMDS_MeshElement*>& theElems)
 {
   if ( theElems.empty() )
     return;
@@ -802,13 +849,13 @@ static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
   // Element can belong to several groups
   if ( !theGroups.empty() )
   {
-    set<SMESHDS_GroupBase*>::iterator GrIt = theGroups.begin();
+    std::set<SMESHDS_GroupBase*>::iterator GrIt = theGroups.begin();
     for ( ; GrIt != theGroups.end(); GrIt++ )
     {
       SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *GrIt );
       if ( !group || group->IsEmpty() ) continue;
 
-      list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
+      std::vector<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
       for ( ; elIt != theElems.end(); elIt++ )
       {
         group->SMDSGroup().Remove( *elIt );
@@ -817,93 +864,95 @@ static void removeFromContainers (map<int,SMESHDS_SubMesh*>&     theSubMeshes,
     }
   }
 
-  const bool deleted=true;
+  //const bool deleted=true;
 
   // Rm from sub-meshes
   // Element should belong to only one sub-mesh
-  if ( !theSubMeshes.empty() )
-  {
-    SMESHDS_Mesh* mesh = theSubMeshes.begin()->second->GetParent();
-    list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
-    if ( isNode ) {
-      for ( ; elIt != theElems.end(); ++elIt )
-        if ( SMESHDS_SubMesh* sm = mesh->MeshElements( (*elIt)->getshapeId() ))
-          sm->RemoveNode( static_cast<const SMDS_MeshNode*> (*elIt), deleted );
-    }
-    else {
-      for ( ; elIt != theElems.end(); ++elIt )
-        if ( SMESHDS_SubMesh* sm = mesh->MeshElements( (*elIt)->getshapeId() ))
-          sm->RemoveElement( *elIt, deleted );
-    }
-  }
+  // if ( theMesh->SubMeshes()->more() )
+  // {
+  //   std::list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
+  //   if ( isNode ) {
+  //     for ( ; elIt != theElems.end(); ++elIt )
+  //       if ( SMESHDS_SubMesh* sm = theMesh->MeshElements( (*elIt)->getshapeId() ))
+  //         sm->RemoveNode( static_cast<const SMDS_MeshNode*> (*elIt), deleted );
+  //   }
+  //   else {
+  //     for ( ; elIt != theElems.end(); ++elIt )
+  //       if ( SMESHDS_SubMesh* sm = theMesh->MeshElements( (*elIt)->getshapeId() ))
+  //         sm->RemoveElement( *elIt, deleted );
+  //   }
+  // }
 }
 
 //=======================================================================
 //function : RemoveNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::RemoveNode(const SMDS_MeshNode * n)
 {
-  if ( n->NbInverseElements() == 0 && !(hasConstructionEdges() || hasConstructionFaces()))
-  {
-    SMESHDS_SubMesh* subMesh=0;
-    map<int,SMESHDS_SubMesh*>::iterator SubIt =
-      myShapeIndexToSubMesh.find( n->getshapeId() );
-    if ( SubIt != myShapeIndexToSubMesh.end() )
-      subMesh = SubIt->second;
-    else
-      SubIt = myShapeIndexToSubMesh.begin();
-    for ( ; !subMesh && SubIt != myShapeIndexToSubMesh.end(); SubIt++ )
-      if (!SubIt->second->IsComplexSubmesh() && SubIt->second->Contains( n ))
-        subMesh = SubIt->second;
-
-    RemoveFreeNode( n, subMesh, true);
+  if ( RemoveFreeNode( n, 0, true ))
     return;
+
+  myScript->RemoveNode(n->GetID());
+
+  // remove inverse elements from the sub-meshes
+  for ( SMDS_ElemIteratorPtr eIt = n->GetInverseElementIterator(); eIt->more() ; )
+  {
+    const SMDS_MeshElement* e = eIt->next();
+    if ( SMESHDS_SubMesh * sm = MeshElements( e->getshapeId() ))
+      sm->RemoveElement( e );
   }
+  if ( SMESHDS_SubMesh * sm = MeshElements( n->getshapeId() ))
+    sm->RemoveNode( n );
     
-  myScript->RemoveNode(n->GetID());
   
-  list<const SMDS_MeshElement *> removedElems;
-  list<const SMDS_MeshElement *> removedNodes;
+  std::vector<const SMDS_MeshElement *> removedElems;
+  std::vector<const SMDS_MeshElement *> removedNodes;
 
   SMDS_Mesh::RemoveElement( n, removedElems, removedNodes, true );
 
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedNodes, true );
+  removeFromContainers( this, myGroups, removedElems );
+  removeFromContainers( this, myGroups, removedNodes );
 }
 
 //=======================================================================
 //function : RemoveFreeNode
 //purpose  : 
 //=======================================================================
-void SMESHDS_Mesh::RemoveFreeNode(const SMDS_MeshNode * n,
+bool SMESHDS_Mesh::RemoveFreeNode(const SMDS_MeshNode * n,
                                   SMESHDS_SubMesh *     subMesh,
                                   bool                  fromGroups)
 {
+  if ( n->NbInverseElements() > 0 )
+    return false;
+
   myScript->RemoveNode(n->GetID());
 
   // Rm from group
   // Node can belong to several groups
-  if (fromGroups && !myGroups.empty()) {
-    set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
+  if ( fromGroups && !myGroups.empty() ) {
+    std::set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
     for (; GrIt != myGroups.end(); GrIt++) {
       SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>(*GrIt);
-      if (!group || group->IsEmpty()) continue;
-      group->SMDSGroup().Remove(n);
+      if (group && group->GetType() == SMDSAbs_Node )
+        group->SMDSGroup().Remove(n);
     }
   }
 
   // Rm from sub-mesh
   // Node should belong to only one sub-mesh
-  if( subMesh )
-    subMesh->RemoveNode(n,/*deleted=*/false);
+  if ( !subMesh || !subMesh->RemoveNode( n ))
+    if (( subMesh = MeshElements( n->getshapeId() )))
+      subMesh->RemoveNode(n);
 
   SMDS_Mesh::RemoveFreeElement(n);
+
+  return true;
 }
 
 //=======================================================================
 //function : RemoveElement
-//purpose  : 
+//purpose  :
 //========================================================================
 void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
 {
@@ -912,26 +961,24 @@ void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
     RemoveNode( static_cast<const SMDS_MeshNode*>( elt ));
     return;
   }
-  if (!hasConstructionEdges() && !hasConstructionFaces())
+  //if (!hasConstructionEdges() && !hasConstructionFaces())
   {
     SMESHDS_SubMesh* subMesh=0;
-    map<int,SMESHDS_SubMesh*>::iterator SubIt = myShapeIndexToSubMesh.begin();
-    for ( ; !subMesh && SubIt != myShapeIndexToSubMesh.end(); SubIt++ )
-      if (!SubIt->second->IsComplexSubmesh() && SubIt->second->Contains( elt ))
-        subMesh = SubIt->second;
-    //MESSAGE("subMesh " << elt->getshapeId());
-    RemoveFreeElement( elt, subMesh, true);
+    if ( elt->getshapeId() > 0 )
+      subMesh = MeshElements( elt->getshapeId() );
+
+    RemoveFreeElement( elt, subMesh, true );
     return;
   }
  
   myScript->RemoveElement(elt->GetID());
 
-  list<const SMDS_MeshElement *> removedElems;
-  list<const SMDS_MeshElement *> removedNodes;
+  std::vector<const SMDS_MeshElement *> removedElems;
+  std::vector<const SMDS_MeshElement *> removedNodes;
 
-  SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false);
+  SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes );
   
-  removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
+  removeFromContainers( this, myGroups, removedElems );
 }
 
 //=======================================================================
@@ -942,22 +989,21 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
                                      SMESHDS_SubMesh *        subMesh,
                                      bool                     fromGroups)
 {
-  //MESSAGE(" --------------------------------> SMESHDS_Mesh::RemoveFreeElement " << subMesh << " " << fromGroups);
   if (elt->GetType() == SMDSAbs_Node) {
-    RemoveFreeNode( static_cast<const SMDS_MeshNode*>(elt), subMesh);
+    RemoveFreeNode( static_cast<const SMDS_MeshNode*>(elt), subMesh, fromGroups);
     return;
   }
 
-  if (hasConstructionEdges() || hasConstructionFaces())
-    // this methods is only for meshes without descendants
-    return;
+  // if (hasConstructionEdges() || hasConstructionFaces())
+  //   // this methods is only for meshes without descendants
+  //   return;
 
   myScript->RemoveElement(elt->GetID());
 
   // Rm from group
-  // Node can belong to several groups
+  // Element can belong to several groups
   if ( fromGroups && !myGroups.empty() ) {
-    set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
+    std::set<SMESHDS_GroupBase*>::iterator GrIt = myGroups.begin();
     for (; GrIt != myGroups.end(); GrIt++) {
       SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>(*GrIt);
       if (group && !group->IsEmpty())
@@ -967,10 +1013,12 @@ void SMESHDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elt,
 
   // Rm from sub-mesh
   // Element should belong to only one sub-mesh
-  if( subMesh )
-    subMesh->RemoveElement(elt, /*deleted=*/false);
+  if ( !subMesh && elt->getshapeId() > 0 )
+    subMesh = MeshElements( elt->getshapeId() );
+  if ( subMesh )
+    subMesh->RemoveElement( elt );
 
-  SMDS_Mesh::RemoveFreeElement(elt);
+  SMDS_Mesh::RemoveFreeElement( elt );
 }
 
 //================================================================================
@@ -985,9 +1033,9 @@ void SMESHDS_Mesh::ClearMesh()
   SMDS_Mesh::Clear();
 
   // clear submeshes
-  map<int,SMESHDS_SubMesh*>::iterator sub, subEnd = myShapeIndexToSubMesh.end();
-  for ( sub = myShapeIndexToSubMesh.begin(); sub != subEnd; ++sub )
-    sub->second->Clear();
+  SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+  while ( SMESHDS_SubMesh* sm = const_cast< SMESHDS_SubMesh* >( smIt->next() ))
+    sm->Clear();
 
   // clear groups
   TGroups::iterator group, groupEnd = myGroups.end();
@@ -997,16 +1045,18 @@ void SMESHDS_Mesh::ClearMesh()
       g->Clear();
       g->SetType( groupType );
     }
+    else
+    {
+      (*group)->Extent(); // to free cached elements in GroupOnFilter's
+    }
   }
 }
 
 //================================================================================
 /*!
  * \brief return submesh by shape
-  * \param shape - the sub-shape
-  * \retval SMESHDS_SubMesh* - the found submesh
-  *
- * search of submeshes is optimized
+ * \param shape - the sub-shape
+ * \retval SMESHDS_SubMesh* - the found submesh
  */
 //================================================================================
 
@@ -1015,118 +1065,87 @@ SMESHDS_SubMesh* SMESHDS_Mesh::getSubmesh( const TopoDS_Shape & shape )
   if ( shape.IsNull() )
     return 0;
 
-  if ( !myCurSubShape.IsNull() && shape.IsSame( myCurSubShape ))
-    return myCurSubMesh;
-
-  getSubmesh( ShapeToIndex( shape ));
-  myCurSubShape = shape;
-  return myCurSubMesh;
-}
-
-//================================================================================
-/*!
- * \brief return submesh by sub-shape index
-  * \param Index - the sub-shape index
-  * \retval SMESHDS_SubMesh* - the found submesh
- * search of submeshes is optimized
- */
-//================================================================================
-
-SMESHDS_SubMesh* SMESHDS_Mesh::getSubmesh( const int Index )
-{
-  //Update or build submesh
-  if ( Index != myCurSubID ) {
-    map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find( Index );
-    if ( it == myShapeIndexToSubMesh.end() )
-      it = myShapeIndexToSubMesh.insert( make_pair(Index, new SMESHDS_SubMesh(this, Index) )).first;
-    myCurSubMesh = it->second;
-    myCurSubID = Index;
-    myCurSubShape.Nullify(); // myCurSubShape no more corresponds to submesh
-  }
-  return myCurSubMesh;
+  return NewSubMesh( ShapeToIndex( shape ));
 }
 
 //================================================================================
 /*!
  * \brief Add element or node to submesh
 * \param elem - element to add
 * \param subMesh - submesh to be filled in
+ * \param elem - element to add
+ * \param subMesh - submesh to be filled in
  */
 //================================================================================
 
-bool SMESHDS_Mesh::add(const SMDS_MeshElement* elem, SMESHDS_SubMesh* subMesh )
+int SMESHDS_Mesh::add(const SMDS_MeshElement* elem, SMESHDS_SubMesh* subMesh )
 {
   if ( elem && subMesh ) {
-    if ( elem->GetType() == SMDSAbs_Node )
-      subMesh->AddNode( static_cast<const SMDS_MeshNode* >( elem ));
-    else
-      subMesh->AddElement( elem );
-    return true;
+    subMesh->AddElement( elem );
+    return subMesh->GetID();
   }
-  return false;
+  return 0;
 }
 
 //=======================================================================
 //function : SetNodeOnVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode* aNode,
                                    const TopoDS_Shell & S)
 {
-  if ( add( aNode, getSubmesh(S) ))
+  if ( int shapeID = add( aNode, getSubmesh( S )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition( SMDS_SpacePosition::originSpacePosition() );
+      ( aNode )->SetPosition( SMDS_SpacePosition::originSpacePosition(), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode *      aNode,
                                    const TopoDS_Solid & S)
 {
-  if ( add( aNode, getSubmesh(S) ))
+  if ( int shapeID = add( aNode, getSubmesh( S )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition( SMDS_SpacePosition::originSpacePosition() );
+      ( aNode )->SetPosition( SMDS_SpacePosition::originSpacePosition(), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnFace
-//purpose  : 
+//purpose  :
 //=======================================================================
-void SMESHDS_Mesh::SetNodeOnFace(const SMDS_MeshNode *     aNode,
-                                 const TopoDS_Face & S,
-                                 double              u,
-                                 double              v)
+void SMESHDS_Mesh::SetNodeOnFace(const SMDS_MeshNode * aNode,
+                                 const TopoDS_Face &   S,
+                                 double                u,
+                                 double                v)
 {
-  if ( add( aNode, getSubmesh(S) ))
+  if ( int shapeID = add( aNode, getSubmesh( S )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_FacePosition( u, v)));
+      ( aNode )->SetPosition(SMDS_PositionPtr( new SMDS_FacePosition( u, v )), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnEdge
-//purpose  : 
+//purpose  :
 //=======================================================================
-void SMESHDS_Mesh::SetNodeOnEdge(const SMDS_MeshNode *     aNode,
-                                 const TopoDS_Edge & S,
-                                 double              u)
+void SMESHDS_Mesh::SetNodeOnEdge(const SMDS_MeshNode * aNode,
+                                 const TopoDS_Edge &   S,
+                                 double                u)
 {
-  if ( add( aNode, getSubmesh(S) ))
+  if ( int shapeID = add( aNode, getSubmesh( S )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition(u)));
+      ( aNode )->SetPosition(SMDS_PositionPtr( new SMDS_EdgePosition( u )), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnVertex
-//purpose  : 
+//purpose  :
 //=======================================================================
-void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode *       aNode,
+void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode * aNode,
                                    const TopoDS_Vertex & S)
 {
-  if ( add( aNode, getSubmesh(S) ))
+  if ( int shapeID = add( aNode, getSubmesh( S )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_VertexPosition()));
+      ( aNode )->SetPosition(SMDS_PositionPtr( new SMDS_VertexPosition()), shapeID );
 }
 
 //=======================================================================
@@ -1136,17 +1155,14 @@ void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode *       aNode,
 void SMESHDS_Mesh::UnSetNodeOnShape(const SMDS_MeshNode* aNode)
 {
   int shapeId = aNode->getshapeId();
-  if (shapeId >= 0)
-    {
-      map<int, SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find(shapeId);
-      if (it != myShapeIndexToSubMesh.end())
-        it->second->RemoveNode(aNode, /*deleted=*/false);
-    }
+  if (shapeId > 0)
+    if ( SMESHDS_SubMesh* sm = MeshElements( shapeId ))
+      sm->RemoveNode(aNode);
 }
 
 //=======================================================================
 //function : SetMeshElementOnShape
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement * anElement,
                                          const TopoDS_Shape &     S)
@@ -1161,16 +1177,8 @@ void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement * anElement,
 void SMESHDS_Mesh::UnSetMeshElementOnShape(const SMDS_MeshElement * elem,
                                            const TopoDS_Shape &     S)
 {
-  int Index = myIndexToShape.FindIndex(S);
-
-  map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.find( Index );
-  if ( it != myShapeIndexToSubMesh.end() )
-    {
-      if (elem->GetType() == SMDSAbs_Node)
-        it->second->RemoveNode(static_cast<const SMDS_MeshNode*> (elem), /*deleted=*/false);
-      else
-        it->second->RemoveElement(elem, /*deleted=*/false);
-    }
+  if ( SMESHDS_SubMesh* sm = MeshElements( S ))
+    sm->RemoveElement(elem);
 }
 
 //=======================================================================
@@ -1179,7 +1187,7 @@ void SMESHDS_Mesh::UnSetMeshElementOnShape(const SMDS_MeshElement * elem,
 //=======================================================================
 TopoDS_Shape SMESHDS_Mesh::ShapeToMesh() const
 {
-        return myShape;
+  return myShape;
 }
 
 //=======================================================================
@@ -1207,11 +1215,7 @@ bool SMESHDS_Mesh::IsGroupOfSubShapes (const TopoDS_Shape& theShape) const
 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const TopoDS_Shape & S) const
 {
   int Index = ShapeToIndex(S);
-  TShapeIndexToSubMesh::const_iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter != myShapeIndexToSubMesh.end())
-    return anIter->second;
-  else
-    return NULL;
+  return (SMESHDS_SubMesh *) ( Index ? mySubMeshHolder->Get( Index ) : 0 );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1219,39 +1223,45 @@ SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const TopoDS_Shape & S) const
 ///////////////////////////////////////////////////////////////////////////////
 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const int Index) const
 {
-  TShapeIndexToSubMesh::const_iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter != myShapeIndexToSubMesh.end())
-    return anIter->second;
-  else
-    return NULL;
+  return const_cast< SMESHDS_SubMesh* >( mySubMeshHolder->Get( Index ));
 }
 
 //=======================================================================
 //function : SubMeshIndices
 //purpose  : 
 //=======================================================================
-list<int> SMESHDS_Mesh::SubMeshIndices() const
+std::list<int> SMESHDS_Mesh::SubMeshIndices() const
 {
-  list<int> anIndices;
-  std::map<int,SMESHDS_SubMesh*>::const_iterator anIter = myShapeIndexToSubMesh.begin();
-  for (; anIter != myShapeIndexToSubMesh.end(); anIter++) {
-    anIndices.push_back((*anIter).first);
-  }
+  std::list<int> anIndices;
+  SMESHDS_SubMeshIteratorPtr smIt = SubMeshes();
+  while ( const SMESHDS_SubMesh* sm = smIt->next() )
+    anIndices.push_back( sm->GetID() );
+
   return anIndices;
 }
 
+//=======================================================================
+//function : SubMeshes
+//purpose  : 
+//=======================================================================
+
+SMESHDS_SubMeshIteratorPtr SMESHDS_Mesh::SubMeshes() const
+{
+  return SMESHDS_SubMeshIteratorPtr( mySubMeshHolder->GetIterator() );
+}
+
 //=======================================================================
 //function : GetHypothesis
 //purpose  : 
 //=======================================================================
 
-const list<const SMESHDS_Hypothesis*>&
+const std::list<const SMESHDS_Hypothesis*>&
 SMESHDS_Mesh::GetHypothesis(const TopoDS_Shape & S) const
 {
-  if ( myShapeToHypothesis.IsBound( S.Oriented(TopAbs_FORWARD) ) ) // ignore orientation of S
-     return myShapeToHypothesis.Find( S.Oriented(TopAbs_FORWARD) );
+  if ( myShapeToHypothesis.IsBound( S/*.Oriented(TopAbs_FORWARD)*/ ) ) // ignore orientation of S
+    return myShapeToHypothesis.Find( S/*.Oriented(TopAbs_FORWARD)*/ );
 
-  static list<const SMESHDS_Hypothesis*> empty;
+  static std::list<const SMESHDS_Hypothesis*> empty;
   return empty;
 }
 
@@ -1276,7 +1286,7 @@ bool SMESHDS_Mesh::IsUsedHypothesis(const SMESHDS_Hypothesis * H) const
 //=======================================================================
 SMESHDS_Script* SMESHDS_Mesh::GetScript()
 {
-        return myScript;
+  return myScript;
 }
 
 //=======================================================================
@@ -1285,7 +1295,7 @@ SMESHDS_Script* SMESHDS_Mesh::GetScript()
 //=======================================================================
 void SMESHDS_Mesh::ClearScript()
 {
-        myScript->Clear();
+  myScript->Clear();
 }
 
 //=======================================================================
@@ -1294,9 +1304,8 @@ void SMESHDS_Mesh::ClearScript()
 //=======================================================================
 bool SMESHDS_Mesh::HasMeshElements(const TopoDS_Shape & S) const
 {
-        if (myShape.IsNull()) MESSAGE("myShape is NULL");
-        int Index = myIndexToShape.FindIndex(S);
-        return myShapeIndexToSubMesh.find(Index)!=myShapeIndexToSubMesh.end();
+  int Index = myIndexToShape.FindIndex(S);
+  return mySubMeshHolder->Get( Index );
 }
 
 //=======================================================================
@@ -1305,7 +1314,7 @@ bool SMESHDS_Mesh::HasMeshElements(const TopoDS_Shape & S) const
 //=======================================================================
 bool SMESHDS_Mesh::HasHypothesis(const TopoDS_Shape & S)
 {
-  return myShapeToHypothesis.IsBound(S.Oriented(TopAbs_FORWARD));
+  return myShapeToHypothesis.IsBound(S/*.Oriented(TopAbs_FORWARD)*/);
 }
 
 //=======================================================================
@@ -1314,15 +1323,12 @@ bool SMESHDS_Mesh::HasHypothesis(const TopoDS_Shape & S)
 //=======================================================================
 SMESHDS_SubMesh * SMESHDS_Mesh::NewSubMesh(int Index)
 {
-  SMESHDS_SubMesh* SM = 0;
-  TShapeIndexToSubMesh::iterator anIter = myShapeIndexToSubMesh.find(Index);
-  if (anIter == myShapeIndexToSubMesh.end())
+  SMESHDS_SubMesh* SM = MeshElements( Index );
+  if ( !SM )
   {
     SM = new SMESHDS_SubMesh(this, Index);
-    myShapeIndexToSubMesh[Index]=SM;
+    mySubMeshHolder->Add( Index, SM );
   }
-  else
-    SM = anIter->second;
   return SM;
 }
 
@@ -1341,7 +1347,6 @@ int SMESHDS_Mesh::AddCompoundSubmesh(const TopoDS_Shape& S,
     bool all = ( type == TopAbs_SHAPE );
     if ( all ) // corresponding simple submesh may exist
       aMainIndex = -aMainIndex;
-    //MESSAGE("AddCompoundSubmesh index = " << aMainIndex );
     SMESHDS_SubMesh * aNewSub = NewSubMesh( aMainIndex );
     if ( !aNewSub->IsComplexSubmesh() ) // is empty
     {
@@ -1370,9 +1375,10 @@ const TopoDS_Shape& SMESHDS_Mesh::IndexToShape(int ShapeIndex) const
 {
   try
   {
-    return myIndexToShape.FindKey(ShapeIndex);
+    if ( ShapeIndex > 0 )
+      return myIndexToShape.FindKey(ShapeIndex);
   }
-  catch ( Standard_OutOfRange )
+  catch ( ... )
   {
   }
   static TopoDS_Shape nullShape;
@@ -1387,7 +1393,7 @@ const TopoDS_Shape& SMESHDS_Mesh::IndexToShape(int ShapeIndex) const
 
 int SMESHDS_Mesh::MaxSubMeshIndex() const
 {
-  return myShapeIndexToSubMesh.empty() ? 0 : myShapeIndexToSubMesh.rbegin()->first;
+  return mySubMeshHolder->GetMaxID();
 }
 
 //=======================================================================
@@ -1396,11 +1402,7 @@ int SMESHDS_Mesh::MaxSubMeshIndex() const
 //=======================================================================
 int SMESHDS_Mesh::ShapeToIndex(const TopoDS_Shape & S) const
 {
-  if (myShape.IsNull())
-    MESSAGE("myShape is NULL");
-
   int index = myIndexToShape.FindIndex(S);
-  
   return index;
 }
 
@@ -1410,47 +1412,46 @@ int SMESHDS_Mesh::ShapeToIndex(const TopoDS_Shape & S) const
 //=======================================================================
 void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode* aNode, int Index)
 {
-  //add(aNode, getSubmesh(Index));
-  if ( add( aNode, getSubmesh( Index )))
-    ((SMDS_MeshNode*) aNode)->SetPosition( SMDS_SpacePosition::originSpacePosition());
+  if ( int shapeID = add( aNode, NewSubMesh( Index )))
+    ((SMDS_MeshNode*) aNode)->SetPosition( SMDS_SpacePosition::originSpacePosition(), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnFace
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetNodeOnFace(const SMDS_MeshNode* aNode, int Index, double u, double v)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if ( int shapeID = add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_FacePosition( u, v)));
+      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_FacePosition( u, v )), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnEdge
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetNodeOnEdge(const SMDS_MeshNode* aNode,
                                  int                  Index,
                                  double               u)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if (  int shapeID = add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition(u)));
+      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition( u )), shapeID );
 }
 
 //=======================================================================
 //function : SetNodeOnVertex
-//purpose  : 
+//purpose  :
 //=======================================================================
 void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode* aNode, int Index)
 {
   //Set Position on Node
-  if ( add( aNode, getSubmesh( Index )))
+  if (  int shapeID = add( aNode, NewSubMesh( Index )))
     const_cast< SMDS_MeshNode* >
-      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_VertexPosition()));
+      ( aNode )->SetPosition(SMDS_PositionPtr(new SMDS_VertexPosition()), shapeID );
 }
 
 //=======================================================================
@@ -1460,7 +1461,7 @@ void SMESHDS_Mesh::SetNodeOnVertex(const SMDS_MeshNode* aNode, int Index)
 void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement* anElement,
                                          int                     Index)
 {
-  add( anElement, getSubmesh( Index ));
+  add( anElement, NewSubMesh( Index ));
 }
 
 //=======================================================================
@@ -1472,9 +1473,7 @@ SMESHDS_Mesh::~SMESHDS_Mesh()
   // myScript
   delete myScript;
   // submeshes
-  TShapeIndexToSubMesh::iterator i_sm = myShapeIndexToSubMesh.begin();
-  for ( ; i_sm != myShapeIndexToSubMesh.end(); ++i_sm )
-    delete i_sm->second;
+  delete mySubMeshHolder;
 }
 
 
@@ -1867,7 +1866,7 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolume
-//purpose  : 
+//purpose  : 2nd order pentahedron (prism) with 15 nodes
 //=======================================================================
 SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
                                          const SMDS_MeshNode * n2, 
@@ -1898,7 +1897,7 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 
+//purpose  : 2nd order pentahedron (prism) with 15 nodes
 //=======================================================================
 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
                                                int n4, int n5, int n6,
@@ -1914,10 +1913,96 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
                                  n45,n56,n64,n14,n25,n36);
   return anElem;
 }
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Pentahedron (prism) with 15 nodes
+//=======================================================================
+SMDS_MeshVolume* SMESHDS_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)
+{
+  return AddVolumeWithID(n1->GetID(), n2->GetID(), n3->GetID(),
+                         n4->GetID(), n5->GetID(), n6->GetID(),
+                         n12->GetID(), n23->GetID(), n31->GetID(),
+                         n45->GetID(), n56->GetID(), n64->GetID(),
+                         n14->GetID(), n25->GetID(), n36->GetID(),
+                         ID);
+}
+//=======================================================================
+//function : AddVolume
+//purpose  : 2nd order pentahedron (prism) with 18 nodes
+//=======================================================================
+SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                         const SMDS_MeshNode * n2,
+                                         const SMDS_MeshNode * n3,
+                                         const SMDS_MeshNode * n4,
+                                         const SMDS_MeshNode * n5,
+                                         const SMDS_MeshNode * n6,
+                                         const SMDS_MeshNode * n12,
+                                         const SMDS_MeshNode * n23,
+                                         const SMDS_MeshNode * n31,
+                                         const SMDS_MeshNode * n45,
+                                         const SMDS_MeshNode * n56,
+                                         const SMDS_MeshNode * n64,
+                                         const SMDS_MeshNode * n14,
+                                         const SMDS_MeshNode * n25,
+                                         const SMDS_MeshNode * n36,
+                                         const SMDS_MeshNode * n1245,
+                                         const SMDS_MeshNode * n2356,
+                                         const SMDS_MeshNode * n1346)
+{
+  SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolume(n1,n2,n3,n4,n5,n6,n12,n23,n31,
+                                                 n45,n56,n64,n14,n25,n36,
+                                                 n1245, n2356, n1346);
+  if(anElem)
+    myScript->AddVolume(anElem->GetID(), n1->GetID(), n2->GetID(),
+                        n3->GetID(), n4->GetID(), n5->GetID(), n6->GetID(),
+                        n12->GetID(), n23->GetID(), n31->GetID(),
+                        n45->GetID(), n56->GetID(), n64->GetID(),
+                        n14->GetID(), n25->GetID(), n36->GetID(),
+                        n1245->GetID(), n2356->GetID(), n1346->GetID());
+  return anElem;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2nd order pentahedron (prism) with 18 nodes
+//=======================================================================
+SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
+                                               int n4, int n5, int n6,
+                                               int n12,int n23,int n31,
+                                               int n45,int n56,int n64,
+                                               int n14,int n25,int n36,
+                                               int n1245, int n2356, int n1346,
+                                               int ID)
+{
+  SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolumeWithID(n1,n2,n3,n4,n5,n6,
+                                                       n12,n23,n31,
+                                                       n45,n56,n64,
+                                                       n14,n25,n36,
+                                                       n1245, n2356, n1346, ID);
+  if(anElem) myScript->AddVolume(ID,n1,n2,n3,n4,n5,n6,n12,n23,n31,
+                                 n45,n56,n64,n14,n25,n36, n1245, n2356, n1346);
+  return anElem;
+}
         
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 2d order Pentahedron with 15 nodes
+//purpose  : 2d order Pentahedron with 18 nodes
 //=======================================================================
 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                                const SMDS_MeshNode * n2,
@@ -1934,6 +2019,9 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                                const SMDS_MeshNode * n14,
                                                const SMDS_MeshNode * n25,
                                                const SMDS_MeshNode * n36,
+                                               const SMDS_MeshNode * n1245,
+                                               const SMDS_MeshNode * n2356,
+                                               const SMDS_MeshNode * n1346,
                                                int ID)
 {
   return AddVolumeWithID(n1->GetID(), n2->GetID(), n3->GetID(),
@@ -1941,7 +2029,7 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                          n12->GetID(), n23->GetID(), n31->GetID(),
                          n45->GetID(), n56->GetID(), n64->GetID(),
                          n14->GetID(), n25->GetID(), n36->GetID(),
-                         ID);
+                         n1245->GetID(), n2356->GetID(), n1346->GetID(), ID);
 }
 
 
@@ -2114,22 +2202,22 @@ SMDS_MeshVolume* SMESHDS_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 * n5,
+                                               const SMDS_MeshNode * n6,
                                                const SMDS_MeshNode * n7,
-                                               const SMDS_MeshNode * n8, 
+                                               const SMDS_MeshNode * n8,
                                                const SMDS_MeshNode * n12,
                                                const SMDS_MeshNode * n23,
                                                const SMDS_MeshNode * n34,
-                                               const SMDS_MeshNode * n41, 
+                                               const SMDS_MeshNode * n41,
                                                const SMDS_MeshNode * n56,
                                                const SMDS_MeshNode * n67,
                                                const SMDS_MeshNode * n78,
-                                               const SMDS_MeshNode * n85, 
+                                               const SMDS_MeshNode * n85,
                                                const SMDS_MeshNode * n15,
                                                const SMDS_MeshNode * n26,
                                                const SMDS_MeshNode * n37,
-                                               const SMDS_MeshNode * n48, 
+                                               const SMDS_MeshNode * n48,
                                                const SMDS_MeshNode * n1234,
                                                const SMDS_MeshNode * n1256,
                                                const SMDS_MeshNode * n2367,
@@ -2148,162 +2236,14 @@ SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                          n1458->GetID(),n5678->GetID(),nCenter->GetID(), ID);
 }
 
-void SMESHDS_Mesh::compactMesh()
+void SMESHDS_Mesh::CompactMesh()
 {
-  int newNodeSize = 0;
-  int nbNodes = myNodes.size();
-  int nbVtkNodes = myGrid->GetNumberOfPoints();
-  MESSAGE("nbNodes=" << nbNodes << " nbVtkNodes=" << nbVtkNodes);
-  int nbNodeTemp = nbVtkNodes;
-  if (nbNodes > nbVtkNodes)
-    nbNodeTemp = nbNodes;
-  vector<int> idNodesOldToNew;
-  idNodesOldToNew.clear();
-  idNodesOldToNew.resize(nbNodeTemp, -1); // all unused id will be -1
-
-  for (int i = 0; i < nbNodes; i++)
-    {
-      if (myNodes[i])
-        {
-          int vtkid = myNodes[i]->getVtkId();
-          idNodesOldToNew[vtkid] = i; // old vtkId --> old smdsId (valid smdsId are >= 0)
-          newNodeSize++;
-        }
-    }
-  bool areNodesModified = (newNodeSize < nbVtkNodes);
-  MESSAGE("------------------------- compactMesh Nodes Modified: " << areNodesModified);
-  areNodesModified = true;
-
-  int newCellSize = 0;
-  int nbCells = myCells.size();
-  int nbVtkCells = myGrid->GetNumberOfCells();
-  MESSAGE("nbCells=" << nbCells << " nbVtkCells=" << nbVtkCells);
-  int nbCellTemp = nbVtkCells;
-  if (nbCells > nbVtkCells)
-    nbCellTemp = nbCells;
-  vector<int> idCellsOldToNew;
-  idCellsOldToNew.clear();
-  idCellsOldToNew.resize(nbCellTemp, -1); // all unused id will be -1
-
-  for (int i = 0; i < nbCells; i++)
-    {
-      if (myCells[i])
-        {
-//          //idCellsOldToNew[i] = myCellIdVtkToSmds[i]; // valid vtk indexes are > = 0
-//          int vtkid = myCells[i]->getVtkId();
-//          idCellsOldToNew[vtkid] = i; // old vtkId --> old smdsId (not used in input)
-          newCellSize++;
-        }
-    }
-  if (areNodesModified)
-    myGrid->compactGrid(idNodesOldToNew, newNodeSize, idCellsOldToNew, newCellSize);
-  else
-    myGrid->compactGrid(idNodesOldToNew, 0, idCellsOldToNew, newCellSize);
-
-  int nbVtkPts = myGrid->GetNumberOfPoints();
-  nbVtkCells = myGrid->GetNumberOfCells();
-  if (nbVtkPts != newNodeSize)
-    {
-      MESSAGE("===> nbVtkPts != newNodeSize " << nbVtkPts << " " << newNodeSize);
-      if (nbVtkPts > newNodeSize) newNodeSize = nbVtkPts; // several points with same SMDS Id
-    }
-  if (nbVtkCells != newCellSize)
-    {
-      MESSAGE("===> nbVtkCells != newCellSize " << nbVtkCells << " " << newCellSize);
-      if (nbVtkCells > newCellSize) newCellSize = nbVtkCells; // several cells with same SMDS Id
-    }
-
-  // --- SMDS_MeshNode and myNodes (id in SMDS and in VTK are the same), myNodeIdFactory
-
-  if (areNodesModified)
-    {
-      MESSAGE("-------------- modify myNodes");
-      SetOfNodes newNodes;
-      newNodes.resize(newNodeSize+1,0); // 0 not used, SMDS numbers 1..n
-      int newSmdsId = 0;
-      for (int i = 0; i < nbNodes; i++)
-        {
-          if (myNodes[i])
-            {
-              newSmdsId++; // SMDS id start to 1
-              int oldVtkId = myNodes[i]->getVtkId();
-              int newVtkId = idNodesOldToNew[oldVtkId];
-              //MESSAGE("myNodes["<< i << "] vtkId " << oldVtkId << " --> " << newVtkId);
-              myNodes[i]->setVtkId(newVtkId);
-              myNodes[i]->setId(newSmdsId);
-              newNodes[newSmdsId] = myNodes[i];
-              //MESSAGE("myNodes["<< i << "] --> newNodes[" << newSmdsId << "]");
-            }
-        }
-      myNodes.swap(newNodes);
-      this->myNodeIDFactory->emptyPool(newSmdsId); // newSmdsId = number of nodes
-      MESSAGE("myNodes.size " << myNodes.size());
-    }
-
-  // --- SMDS_MeshCell, myCellIdVtkToSmds, myCellIdSmdsToVtk, myCells
-
-  int vtkIndexSize = myCellIdVtkToSmds.size();
-  int maxVtkId = -1;
-  for (int oldVtkId = 0; oldVtkId < vtkIndexSize; oldVtkId++)
-    {
-      int oldSmdsId = this->myCellIdVtkToSmds[oldVtkId];
-      if (oldSmdsId > 0)
-        {
-          int newVtkId = idCellsOldToNew[oldVtkId];
-          if (newVtkId > maxVtkId)
-            maxVtkId = newVtkId;
-          //MESSAGE("myCells["<< oldSmdsId << "] vtkId " << oldVtkId << " --> " << newVtkId);
-          myCells[oldSmdsId]->setVtkId(newVtkId);
-        }
-    }
-//  MESSAGE("myCells.size()=" << myCells.size()
-//          << " myCellIdSmdsToVtk.size()=" << myCellIdSmdsToVtk.size()
-//          << " myCellIdVtkToSmds.size()=" << myCellIdVtkToSmds.size() );
-
-  SetOfCells newCells;
-  //vector<int> newSmdsToVtk;
-  vector<int> newVtkToSmds;
-
-  assert(maxVtkId < newCellSize);
-  newCells.resize(newCellSize+1, 0); // 0 not used, SMDS numbers 1..n
-  //newSmdsToVtk.resize(newCellSize+1, -1);
-  newVtkToSmds.resize(newCellSize+1, -1);
-
-  int myCellsSize = myCells.size();
-  int newSmdsId = 0;
-  for (int i = 0; i < myCellsSize; i++)
-    {
-      if (myCells[i])
-        {
-          newSmdsId++; // SMDS id start to 1
-          assert(newSmdsId <= newCellSize);
-          newCells[newSmdsId] = myCells[i];
-          newCells[newSmdsId]->setId(newSmdsId);
-          //MESSAGE("myCells["<< i << "] --> newCells[" << newSmdsId << "]");
-          int idvtk = myCells[i]->getVtkId();
-          //newSmdsToVtk[newSmdsId] = idvtk;
-          assert(idvtk < newCellSize);
-          newVtkToSmds[idvtk] = newSmdsId;
-        }
-    }
+  if ( IsCompacted() )
+    return;
 
-  myCells.swap(newCells);
-  //myCellIdSmdsToVtk.swap(newSmdsToVtk);
-  myCellIdVtkToSmds.swap(newVtkToSmds);
-  MESSAGE("myCells.size()=" << myCells.size()
-          << " myCellIdVtkToSmds.size()=" << myCellIdVtkToSmds.size() );
-  this->myElementIDFactory->emptyPool(newSmdsId);
+  SMDS_Mesh::CompactMesh();
 
   this->myScript->SetModified(true); // notify GUI client for buildPrs when update
-
-  // --- compact list myNodes and myElements in submeshes
-
-  map<int,SMESHDS_SubMesh*>::iterator it = myShapeIndexToSubMesh.begin();
-  for(; it != myShapeIndexToSubMesh.end(); ++it)
-    {
-      (*it).second->compactList();
-    }
-
 }
 
 void SMESHDS_Mesh::CleanDownWardConnectivity()