Salome HOME
54355: 'Compute' button is absent for 'Number of the double nodes' value in 'Mesh...
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
index 1e7dd6ab39c81a6925d7b1c4336c059b2b22559e..ce820acbf49b83e0db6ab2f647268db869b66863 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //  $Header: 
 //
 #include "SMESHDS_SubMesh.hxx"
-#include "SMESHDS_Mesh.hxx"
 
-#include "utilities.h"
+#include "SMDS_ElementFactory.hxx"
+#include "SMDS_IteratorOnIterators.hxx"
 #include "SMDS_SetIterator.hxx"
-#include <iostream>
-#include <cassert>
+#include "SMESHDS_Mesh.hxx"
+
+#include <utilities.h>
+
+namespace
+{
+  typedef const SMDS_MeshElement* PElem;
+  typedef const SMDS_MeshNode*    PNode;
+
+  typedef SMDS_SetIterator< PElem, PElem const *,
+                            SMDS::SimpleAccessor< PElem, PElem const * >,
+                            SMDS::NonNullFilter< PElem > >                 EArrayIterator;
+
+  typedef SMDS_SetIterator< PNode, PNode const *,
+                            SMDS::SimpleAccessor< PNode, PNode const * >,
+                            SMDS::NonNullFilter< PNode > >                 NArrayIterator;
 
-using namespace std;
+  int ind1st( SMDSAbs_ElementType t )
+  {
+    return t == SMDSAbs_Node;
+  }
 
+  //=======================================================================
+  //class : _MyElemIteratorFromNodeIterator
+  //=======================================================================
+  class _MyElemIteratorFromNodeIterator : public SMDS_ElemIterator
+  {
+    SMDS_NodeIteratorPtr myItr;
+  public:
+    _MyElemIteratorFromNodeIterator(SMDS_NodeIteratorPtr nodeItr): myItr( nodeItr ) {}
+    bool more()                    { return myItr->more(); }
+    const SMDS_MeshElement* next() { return myItr->next(); }
+  };
+}
 
 //================================================================================
 /*!
@@ -43,12 +72,14 @@ using namespace std;
  */
 //================================================================================
 
-SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
+SMESHDS_SubMesh::SMESHDS_SubMesh(const SMESHDS_Mesh *parent, int index)
+  : SMDS_ElementHolder( parent )
 {
   myParent = parent;
   myIndex = index;
-  myUnusedIdNodes = 0;
-  myUnusedIdElements = 0;
+  myNbElements = 0;
+  myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
 }
 
 //================================================================================
@@ -66,16 +97,16 @@ SMESHDS_SubMesh::~SMESHDS_SubMesh()
 //purpose  :
 //=======================================================================
 
-void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
+void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
 {
   if (!IsComplexSubmesh())
   {
-    if ( ME->GetType() == SMDSAbs_Node )
+    if ( elem->GetType() == SMDSAbs_Node )
     {
-      AddNode( static_cast< const SMDS_MeshNode* >( ME ));
+      AddNode( static_cast< const SMDS_MeshNode* >( elem ));
       return;
     }
-    int oldShapeId = ME->getshapeId();
+    int oldShapeId = elem->GetShapeID();
     if ( oldShapeId > 0 )
     {
       if (oldShapeId != myIndex)
@@ -83,28 +114,13 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
         throw SALOME_Exception
           (LOCALIZED("add element in subshape already belonging to a subshape"));
       }
-      int idInSubShape = ME->getIdInShape();
-      if (idInSubShape >= 0)
-      {
-        MESSAGE("add element in subshape already belonging to that subshape "
-                << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
-        // check if ok: do nothing if ok
-        if (idInSubShape >= (int)myElements.size())
-        {
-          throw SALOME_Exception(LOCALIZED("out of bounds"));
-        }
-        if (ME != myElements[idInSubShape])
-        {
-          throw SALOME_Exception(LOCALIZED("not the same element"));
-        }
-        return;
-      }
     }
 
-    SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
-    elem->setShapeId(myIndex);
-    elem->setIdInShape(myElements.size());
-    myElements.push_back(ME);
+    elem->setShapeID( myIndex );
+    myNbElements++;
+
+    // remember element with smallest ID to optimize iteration on them
+    add( elem );
   }
 }
 
@@ -113,70 +129,60 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
 //purpose  :
 //=======================================================================
 
-bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
+bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
 {
-  if (!ME)
+  if ( myNbElements == 0 || !elem || elem->IsNull() || elem->getshapeId() != myIndex )
   {
     return false;
   }
-  if (!IsComplexSubmesh())
+  if ( !IsComplexSubmesh() )
   {
-    if ( ME->getshapeId() != myIndex ) // elem not in a pool can loose it's data already
-    {
-      if ( isElemDeleted )
-        for ( size_t i = 0; i < myElements.size(); ++i )
-          if ( myElements[i] == ME )
-          {
-            myElements[i] = 0;
-            ++myUnusedIdElements;
-            return true;
-          }
-      return false;
-    }
-    int idInSubShape = ME->getIdInShape();
-    SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
-    elem->setShapeId(0);
-    elem->setIdInShape(-1);
-    if ((idInSubShape >= 0) && (idInSubShape < (int) myElements.size()))
+    elem->setShapeID( 0 );
+    myNbElements--;
+
+    const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
+    if ( elem1st == elem )
     {
-      myElements[idInSubShape] = 0; // this vector entry is no more used
-      if ( ++myUnusedIdElements == (int) myElements.size() )
+      if ( myNbElements > 0 )
+      {
+        SMDS_ElemIteratorPtr it = myParent->shapeElementsIterator( myIndex, 1, elem1st );
+        if ( it->more() )
+          elem1st = it->next();
+        else
+          throw SALOME_Exception(LOCALIZED("invalid myNbElements"));
+      }
+      else
       {
-        clearVector( myElements );
-        myUnusedIdElements = 0;
+        elem1st = 0;
       }
-      return true;
     }
-    return false;
+    return true;
   }
   return false;
 }
 
 //=======================================================================
 //function : AddNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
 {
   if ( !IsComplexSubmesh() )
   {
-    const int idInSubShape = N->getIdInShape();
-    const int shapeId      = N->getshapeId();
-    if ((shapeId > 0) && (idInSubShape >= 0))
+    const int shapeId = N->getshapeId();
+    if ( shapeId > 0 )
     {
       if ( shapeId != myIndex )
         throw SALOME_Exception
           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
-      if ( idInSubShape >= (int)myNodes.size() || myNodes[ idInSubShape ] != N )
-        throw SALOME_Exception
-          (LOCALIZED("a node with wrong idInSubShape is re-added to the same sub-mesh"));
       return; // already in
     }
-    SMDS_MeshNode* node = (SMDS_MeshNode*)(N);
-    node->setShapeId(myIndex);
-    node->setIdInShape(myNodes.size());
-    myNodes.push_back(N);
+    N->setShapeID( myIndex );
+    myNbNodes++;
+
+    // remember node with smallest ID to optimize iteration on them
+    add( N );
   }
 }
 
@@ -185,37 +191,35 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
 //purpose  :
 //=======================================================================
 
-bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
+bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
 {
-  if (!IsComplexSubmesh())
+  if ( myNbNodes == 0 || !N || N->getshapeId() != myIndex )
   {
-    if ( N->getshapeId() != myIndex )
-    {
-      if ( isNodeDeleted )
-        for ( size_t i = 0; i < myNodes.size(); ++i )
-          if ( myNodes[i] == N )
-          {
-            myNodes[i] = 0;
-            ++myUnusedIdNodes;
-            return true;
-          }
-      return false;
-    }
-    int idInSubShape = N->getIdInShape();
-    SMDS_MeshNode* node = (SMDS_MeshNode*) (N);
-    node->setShapeId(0);
-    node->setIdInShape(-1);
-    if ((idInSubShape >= 0) && (idInSubShape < (int) myNodes.size()))
+    return false;
+  }
+  if ( !IsComplexSubmesh() )
+  {
+    N->setShapeID( 0 );
+    myNbNodes--;
+
+    const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
+    if ( node1st == N )
     {
-      myNodes[idInSubShape] = 0; // this vector entry is no more used
-      if ( ++myUnusedIdNodes == (int) myNodes.size() )
+      if ( myNbNodes > 0 )
       {
-        clearVector( myNodes );
-        myUnusedIdNodes = 0;
+        SMDS_NodeIteratorPtr it =
+          myParent->shapeNodesIterator( myIndex, 1, static_cast< PNode >( node1st ));
+        if ( it->more() )
+          node1st = it->next();
+        else
+          throw SALOME_Exception(LOCALIZED("invalid myNbNodes"));
+      }
+      else
+      {
+        node1st = 0;
       }
-      return true;
     }
-    return false;
+    return true;
   }
   return false;
 }
@@ -228,10 +232,10 @@ bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
 int SMESHDS_SubMesh::NbElements() const
 {
   if ( !IsComplexSubmesh() )
-    return myElements.size() - myUnusedIdElements;
+    return myNbElements;
 
   int nbElems = 0;
-  set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
+  TSubMeshSet::const_iterator it = mySubMeshes.begin();
   for ( ; it != mySubMeshes.end(); it++ )
     nbElems += (*it)->NbElements();
 
@@ -240,69 +244,32 @@ int SMESHDS_SubMesh::NbElements() const
 
 //=======================================================================
 //function : NbNodes
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMESHDS_SubMesh::NbNodes() const
 {
   if ( !IsComplexSubmesh() )
-    return myNodes.size() - myUnusedIdNodes;
+    return myNbNodes;
 
   int nbElems = 0;
-  set<const SMESHDS_SubMesh*>::const_iterator it = mySubMeshes.begin();
+  TSubMeshSet::const_iterator it = mySubMeshes.begin();
   for ( ; it != mySubMeshes.end(); it++ )
     nbElems += (*it)->NbNodes();
 
   return nbElems;
 }
 
-/*!
- * template class used for iteration on submesh elements. Interface of iterator remains
- * unchanged after redesign of SMDS to avoid modification everywhere in SMESH.
- * instances are stored in shared_ptr for automatic destruction.
- * Container is copied for iteration, because original can be modified
- * by addition of elements, for instance, and then reallocated (vector)
- */
-template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
-{
-protected:
-  typename TSET::const_iterator _it, _end;
-  TSET _table;
-public:
-  MySetIterator(const TSET& table)
-  {
-    _table = table;
-    _it = _table.begin();
-    _end = _table.end();
-    while ((_it != _end) && (*_it == 0))
-      _it++;
-  }
-
-  virtual bool more()
-  {
-    while ((_it != _end) && (*_it == 0))
-      _it++;
-    return (_it != _end);
-  }
-
-  virtual ELEM next()
-  {
-    ELEM e = *_it;
-    _it++;
-    return e;
-  }
-};
-
 // =====================
 // class MyIterator
 // =====================
 
 template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
 {
- public:
-  MyIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
+public:
+  MyIterator (const TSubMeshSet& theSubMeshes)
     : myMore(false), mySubIt( theSubMeshes.begin() ), mySubEnd( theSubMeshes.end() )
-    {}
+  {}
   bool more()
   {
     while (( !myElemIt.get() || !myElemIt->more() ) && mySubIt != mySubEnd)
@@ -320,14 +287,14 @@ template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
       elem = myElemIt->next();
     return elem;
   }
- protected:
+protected:
   virtual boost::shared_ptr< SMDS_Iterator<VALUE> >
-    getElements(const SMESHDS_SubMesh*) const = 0;
+  getElements(const SMESHDS_SubMesh*) const = 0;
 
- private:
-  bool                                        myMore;
-  set<const SMESHDS_SubMesh*>::const_iterator mySubIt, mySubEnd;
-  boost::shared_ptr< SMDS_Iterator<VALUE> >   myElemIt;
+private:
+  bool                                      myMore;
+  TSubMeshSet::const_iterator               mySubIt, mySubEnd;
+  boost::shared_ptr< SMDS_Iterator<VALUE> > myElemIt;
 };
 
 // =====================
@@ -336,8 +303,8 @@ template<typename VALUE> class MyIterator : public SMDS_Iterator<VALUE>
 
 class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
 {
- public:
-  MyElemIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
+public:
+  MyElemIterator (const TSubMeshSet& theSubMeshes)
     :MyIterator<const SMDS_MeshElement*>( theSubMeshes ) {}
   SMDS_ElemIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
   { return theSubMesh->GetElements(); }
@@ -349,28 +316,35 @@ class MyElemIterator: public MyIterator<const SMDS_MeshElement*>
 
 class MyNodeIterator: public MyIterator<const SMDS_MeshNode*>
 {
- public:
-  MyNodeIterator (const set<const SMESHDS_SubMesh*>& theSubMeshes)
+public:
+  MyNodeIterator (const TSubMeshSet& theSubMeshes)
     :MyIterator<const SMDS_MeshNode*>( theSubMeshes ) {}
   SMDS_NodeIteratorPtr getElements(const SMESHDS_SubMesh* theSubMesh) const
   { return theSubMesh->GetNodes(); }
 };
-  
+
 //=======================================================================
 //function : GetElements
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
 {
   if ( IsComplexSubmesh() )
     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
-  return SMDS_ElemIteratorPtr(new MySetIterator<const SMDS_MeshElement*, std::vector<const SMDS_MeshElement*> >(myElements));
+
+  const SMDS_MeshElement* const * elem1st = & my1stElemNode[ ind1st( SMDSAbs_All )];
+  if ( myNbElements < 2 )
+  {
+    return boost::make_shared< EArrayIterator >( elem1st, elem1st + myNbElements );
+  }
+
+  return myParent->shapeElementsIterator( myIndex, myNbElements, *elem1st );
 }
 
 //=======================================================================
 //function : GetNodes
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
@@ -378,7 +352,14 @@ SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
   if ( IsComplexSubmesh() )
     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
 
-  return SMDS_NodeIteratorPtr(new MySetIterator<const SMDS_MeshNode*, std::vector<const SMDS_MeshNode*> >(myNodes));
+  PNode const * node1st =
+    reinterpret_cast< PNode const* >( & my1stElemNode[ ind1st( SMDSAbs_Node )] );
+  if ( myNbNodes < 2 )
+  {
+    return boost::make_shared< NArrayIterator >( node1st, node1st + myNbNodes );
+  }
+
+  return myParent->shapeNodesIterator( myIndex, myNbNodes, *node1st );
 }
 
 //=======================================================================
@@ -388,35 +369,18 @@ SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
 
 bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
 {
-  // DO NOT TRY TO FIND A REMOVED ELEMENT !!
-  //if ( IsComplexSubmesh() || !ME )
-  if (!ME)
+  if ( !ME || ME->IsNull() )
     return false;
 
   if ( IsComplexSubmesh() )
   {
-    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
     for (; aSubIt != mySubMeshes.end(); aSubIt++)
       if ((*aSubIt)->Contains(ME))
         return true;
     return false;
   }
-
-  if (ME->GetType() == SMDSAbs_Node)
-  {
-    int idInShape = ME->getIdInShape();
-    if ((idInShape >= 0) && (idInShape < (int) myNodes.size()))
-      if (myNodes[idInShape] == ME)
-        return true;
-  }
-  else
-  {
-    int idInShape = ME->getIdInShape();
-    if ((idInShape >= 0) && (idInShape < (int) myElements.size()))
-      if (myElements[idInShape] == ME)
-        return true;
-  }
-  return false;
+  return ME->getshapeId() == myIndex;
 }
 
 //=======================================================================
@@ -428,23 +392,23 @@ bool SMESHDS_SubMesh::IsQuadratic() const
 {
   if ( IsComplexSubmesh() )
   {
-    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    TSubMeshSet::const_iterator aSubIt = mySubMeshes.begin();
     for (; aSubIt != mySubMeshes.end(); aSubIt++)
       if ((*aSubIt)->IsQuadratic())
         return true;
     return false;
   }
 
-  for ( size_t i = 0; i < myElements.size(); ++i )
-    if ( myElements[i] )
-      return myElements[i]->IsQuadratic();
+  if ( myNbElements == 0 )
+    return false;
 
-  return false;
+  SMDS_ElemIteratorPtr it = GetElements();
+  return it->more() && it->next()->IsQuadratic();
 }
 
 //=======================================================================
 //function : AddSubMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMESHDS_SubMesh::AddSubMesh( const SMESHDS_SubMesh* theSubMesh )
@@ -475,7 +439,7 @@ void SMESHDS_SubMesh::RemoveAllSubmeshes()
 
 //=======================================================================
 //function : ContainsSubMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
@@ -485,15 +449,13 @@ bool SMESHDS_SubMesh::ContainsSubMesh( const SMESHDS_SubMesh* theSubMesh ) const
 
 //=======================================================================
 //function : GetSubMeshIterator
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
 {
-  typedef set<const SMESHDS_SubMesh*>::const_iterator TIterator;
-  return SMESHDS_SubMeshIteratorPtr
-    ( new SMDS_SetIterator< const SMESHDS_SubMesh*, TIterator >( mySubMeshes.begin(),
-                                                                 mySubMeshes.end()));
+  typedef SMDS_SetIterator< const SMESHDS_SubMesh*, TSubMeshSet::const_iterator > TIterator;
+  return boost::make_shared< TIterator >( mySubMeshes.begin(), mySubMeshes.end());
 }
 
 //=======================================================================
@@ -503,10 +465,26 @@ SMESHDS_SubMeshIteratorPtr SMESHDS_SubMesh::GetSubMeshIterator() const
 
 void SMESHDS_SubMesh::Clear()
 {
-  clearVector( myElements );
-  clearVector( myNodes );
-  myUnusedIdNodes = 0;
-  myUnusedIdElements = 0;
+  if ( myParent && myParent->NbNodes() > 0 )
+  {
+    if ( myNbElements > 0 )
+      for ( SMDS_ElemIteratorPtr it = GetElements(); it->more(); )
+      {
+        const SMDS_MeshElement * elem = it->next();
+        elem->setShapeID( 0 );
+      }
+    if ( myNbNodes > 0 )
+      for ( SMDS_NodeIteratorPtr it = GetNodes(); it->more(); )
+      {
+        const SMDS_MeshNode * elem = it->next();
+        elem->setShapeID( 0 );
+      }
+  }
+
+  myNbElements = 0;
+  myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
+
   if ( NbSubMeshes() > 0 )
   {
     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
@@ -517,62 +495,42 @@ void SMESHDS_SubMesh::Clear()
   }
 }
 
-int SMESHDS_SubMesh::getSize()
-{
-  int c = NbNodes();
-  int d = NbElements();
-  return c+d;
-}
+//=======================================================================
+//function : getElements
+//purpose  : Return iterator on all elements and nodes during compacting
+//=======================================================================
 
-void SMESHDS_SubMesh::compactList()
+SMDS_ElemIteratorPtr SMESHDS_SubMesh::getElements()
 {
-  if ( myUnusedIdElements > 0 )
-  {
-    std::vector<const SMDS_MeshElement*> newElems;
-    newElems.reserve( myElements.size() - myUnusedIdElements );
-    for (size_t i = 0; i < myElements.size(); i++)
-      if (myElements[i])
-      {
-        SMDS_MeshElement* elem = (SMDS_MeshElement*)myElements[i];
-        elem->setIdInShape(newElems.size());
-        newElems.push_back(elem);
-      }
-    myElements.swap(newElems);
-    myUnusedIdElements = 0;
-  }
+  if ( IsComplexSubmesh() ) // return nothing
+    boost::make_shared< EArrayIterator >( & my1stElemNode[0], & my1stElemNode[0] );
 
-  if ( myUnusedIdNodes > 0 )
-  {
-    std::vector<const SMDS_MeshNode*> newNodes;
-    newNodes.reserve( myNodes.size() - myUnusedIdNodes );
-    for (size_t i = 0; i < myNodes.size(); i++)
-      if (myNodes[i])
-      {
-        SMDS_MeshNode* node = (SMDS_MeshNode*)myNodes[i];
-        node->setIdInShape(newNodes.size());
-        newNodes.push_back(node);
-      }
-    myNodes.swap(newNodes);
-    myUnusedIdNodes = 0;
-  }
+  typedef std::vector< SMDS_ElemIteratorPtr > TIterVec;
+  TIterVec iterVec(2);
+  iterVec[0] = GetElements();
+  iterVec[1].reset( new _MyElemIteratorFromNodeIterator( GetNodes() ));
+
+  return boost::make_shared< SMDS_IteratorOnIterators< PElem, TIterVec > >( iterVec );
 }
 
 //=======================================================================
-//function : GetElement
-//purpose  : Return an element by its IdInShape
+//function : tmpClear
+//purpose  : clean up after compacting
 //=======================================================================
 
-const SMDS_MeshElement* SMESHDS_SubMesh::GetElement( size_t idInShape ) const
+void SMESHDS_SubMesh::tmpClear()
 {
-  return ( !IsComplexSubmesh() && idInShape < myElements.size() ) ? myElements[idInShape] : 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
 }
 
 //=======================================================================
-//function : GetElement
-//purpose  : Return a node by its IdInShape
+//function : add
+//purpose  : update my1stElemNode
 //=======================================================================
 
-const SMDS_MeshNode* SMESHDS_SubMesh::GetNode( size_t idInShape ) const
+void SMESHDS_SubMesh::add( const SMDS_MeshElement* elem )
 {
-  return ( !IsComplexSubmesh() && idInShape < myNodes.size() ) ? myNodes[idInShape] : 0;
+  const SMDS_MeshElement* & oldElem = my1stElemNode[ ind1st( elem->GetType() )];
+  if ( !oldElem || oldElem->GetID() > elem->GetID() )
+    oldElem = elem;
 }