Salome HOME
Merge branch 'V9_9_BR'
[modules/smesh.git] / src / SMESHDS / SMESHDS_SubMesh.cxx
index 4a086e3b7073fc8d84be84192fe8c158b8302076..9c6c494fed5a3c7d6d696183ed9835eb18964647 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022  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
 //
 #include "SMESHDS_SubMesh.hxx"
 
-#include "SMESHDS_Mesh.hxx"
-#include "SMDS_SetIterator.hxx"
 #include "SMDS_ElementFactory.hxx"
+#include "SMDS_IteratorOnIterators.hxx"
+#include "SMDS_SetIterator.hxx"
+#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;
+
+  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(); }
+  };
+}
+
 //================================================================================
 /*!
  * \brief Constructor
  */
 //================================================================================
 
-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;
   myNbElements = 0;
   myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
 }
 
 //================================================================================
@@ -81,9 +115,15 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
           (LOCALIZED("add element in subshape already belonging to a subshape"));
       }
     }
+    else
+    {
+      ++myNbElements;
+    }
 
     elem->setShapeID( myIndex );
-    myNbElements++;
+
+    // remember element with smallest ID to optimize iteration on them
+    add( elem );
   }
 }
 
@@ -94,7 +134,7 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
 
 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
 {
-  if ( !elem || elem->IsNull() || elem->getshapeId() != myIndex )
+  if ( myNbElements == 0 || !elem || elem->IsNull() || elem->getshapeId() != myIndex )
   {
     return false;
   }
@@ -102,6 +142,23 @@ bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
   {
     elem->setShapeID( 0 );
     myNbElements--;
+
+    const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
+    if ( elem1st == elem )
+    {
+      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
+      {
+        elem1st = 0;
+      }
+    }
     return true;
   }
   return false;
@@ -124,8 +181,14 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
           (LOCALIZED("a node being in sub-mesh is added to another sub-mesh"));
       return; // already in
     }
+    else
+    {
+      ++myNbNodes;
+    }
     N->setShapeID( myIndex );
-    myNbNodes++;
+
+    // remember node with smallest ID to optimize iteration on them
+    add( N );
   }
 }
 
@@ -136,7 +199,7 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
 
 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
 {
-  if ( !N || N->getshapeId() != myIndex )
+  if ( myNbNodes == 0 || !N || N->getshapeId() != myIndex )
   {
     return false;
   }
@@ -144,6 +207,24 @@ bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
   {
     N->setShapeID( 0 );
     myNbNodes--;
+
+    const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
+    if ( node1st == N )
+    {
+      if ( myNbNodes > 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;
@@ -154,12 +235,12 @@ bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
 //purpose  :
 //=======================================================================
 
-int SMESHDS_SubMesh::NbElements() const
+smIdType SMESHDS_SubMesh::NbElements() const
 {
   if ( !IsComplexSubmesh() )
     return myNbElements;
 
-  int nbElems = 0;
+  smIdType nbElems = 0;
   TSubMeshSet::const_iterator it = mySubMeshes.begin();
   for ( ; it != mySubMeshes.end(); it++ )
     nbElems += (*it)->NbElements();
@@ -172,12 +253,12 @@ int SMESHDS_SubMesh::NbElements() const
 //purpose  :
 //=======================================================================
 
-int SMESHDS_SubMesh::NbNodes() const
+smIdType SMESHDS_SubMesh::NbNodes() const
 {
   if ( !IsComplexSubmesh() )
     return myNbNodes;
 
-  int nbElems = 0;
+  smIdType nbElems = 0;
   TSubMeshSet::const_iterator it = mySubMeshes.begin();
   for ( ; it != mySubMeshes.end(); it++ )
     nbElems += (*it)->NbNodes();
@@ -185,49 +266,6 @@ int SMESHDS_SubMesh::NbNodes() const
   return nbElems;
 }
 
-/*!
- * Template class used for iteration on vector of elements which can resize
- * during iteration. The iterator returns only elements present upon its creation.
- */
-template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
-{
-protected:
-  int _iCur, _iEnd, _iDelta;
-  const TSET& _table;
-public:
-  MySetIterator(const TSET& table, bool reverse): _table( table )
-  {
-    if ( reverse )
-    {
-      _iCur = _table.size()-1;
-      _iEnd = -1;
-      _iDelta = -1;
-    }
-    else
-    {
-      _iCur = 0;
-      _iEnd = _table.size();
-      _iDelta = 1;
-    }
-    if ( more() && !_table[ _iCur ])
-      next();
-  }
-
-  virtual bool more()
-  {
-    return ( _iEnd - _iCur ) * _iDelta > 0;
-  }
-
-  virtual ELEM next()
-  {
-    ELEM e = more() ? _table[ _iCur ] : 0;
-    _iCur += _iDelta;
-    while ( more() && !_table[ _iCur ])
-      _iCur += _iDelta;
-    return e;
-  }
-};
-
 // =====================
 // class MyIterator
 // =====================
@@ -301,7 +339,13 @@ SMDS_ElemIteratorPtr SMESHDS_SubMesh::GetElements() const
   if ( IsComplexSubmesh() )
     return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
 
-  return myParent->shapeElementsIterator( myIndex, myNbElements );
+  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 );
 }
 
 //=======================================================================
@@ -314,7 +358,14 @@ SMDS_NodeIteratorPtr SMESHDS_SubMesh::GetNodes() const
   if ( IsComplexSubmesh() )
     return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
 
-  return myParent->shapeNodesIterator( myIndex, myNbNodes );
+  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 );
 }
 
 //=======================================================================
@@ -438,6 +489,8 @@ void SMESHDS_SubMesh::Clear()
 
   myNbElements = 0;
   myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
+
   if ( NbSubMeshes() > 0 )
   {
     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
@@ -447,3 +500,43 @@ void SMESHDS_SubMesh::Clear()
     }
   }
 }
+
+//=======================================================================
+//function : getElements
+//purpose  : Return iterator on all elements and nodes during compacting
+//=======================================================================
+
+SMDS_ElemIteratorPtr SMESHDS_SubMesh::getElements()
+{
+  if ( IsComplexSubmesh() ) // return nothing
+    boost::make_shared< EArrayIterator >( & my1stElemNode[0], & my1stElemNode[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 : tmpClear
+//purpose  : clean up after compacting
+//=======================================================================
+
+void SMESHDS_SubMesh::tmpClear()
+{
+  my1stElemNode[0] = my1stElemNode[1] = 0;
+}
+
+//=======================================================================
+//function : add
+//purpose  : update my1stElemNode
+//=======================================================================
+
+void SMESHDS_SubMesh::add( const SMDS_MeshElement* elem )
+{
+  const SMDS_MeshElement* & oldElem = my1stElemNode[ ind1st( elem->GetType() )];
+  if ( !oldElem || oldElem->GetID() > elem->GetID() )
+    oldElem = elem;
+}