Salome HOME
Regression of SALOME_TESTS/Grids/smesh/3D_mesh_Extrusion_01/B8
authoreap <eap@opencascade.com>
Wed, 8 Aug 2018 13:55:53 +0000 (16:55 +0300)
committereap <eap@opencascade.com>
Wed, 8 Aug 2018 13:55:53 +0000 (16:55 +0300)
 Optimize iteration on sub-mesh elements

+ minor doc fix

13 files changed:
doc/salome/gui/SMESH/input/basic_meshing_algos.rst
doc/salome/gui/SMESH/input/cartesian_algo.rst
doc/salome/gui/SMESH/input/mesh_preferences.rst
doc/salome/gui/SMESH/input/modifying_meshes.rst
src/SMDS/SMDS_CellOfNodes.hxx
src/SMDS/SMDS_ElementFactory.cxx
src/SMDS/SMDS_ElementFactory.hxx
src/SMDS/SMDS_ElementHolder.cxx
src/SMDS/SMDS_Mesh.cxx
src/SMDS/SMDS_Mesh.hxx
src/SMESHDS/SMESHDS_SubMesh.cxx
src/SMESHDS/SMESHDS_SubMesh.hxx
src/SMESH_SWIG/smeshBuilder.py

index 9033c3104ac8b54769c675e6cac8a16ace70f2d8..692232fd13eff17bfbc9a6f6c4cae80fbda0063f 100644 (file)
@@ -6,7 +6,7 @@ Basic meshing algorithms
 
 The MESH module contains a set of meshing algorithms, which are        used for meshing entities (1D, 2D, 3D sub-shapes) composing geometrical objects.
 
-.. note:: Algorithms added to the module as plug-ins are described in documentation of the plug-ins.
+.. note:: Algorithms added to the module as plug-ins are described in documentation of the plug-ins (menu **Help / User's Guide / Mesh module / Plugins**).
 
 An algorithm represents either an implementation of a certain meshing technique or an interface to the whole meshing program generating elements of several dimensions.
 
index bde18de08d5cce389d8ba135541b195a6bc3f32a..46605bbe409bb60f7e62bb78e076669b5b5618ed 100644 (file)
@@ -15,6 +15,8 @@ boundary.
 .. centered::
        A sphere meshed by Body Fitting algorithm
 
+.. note:: The algorithm creates only 3D elements. To add 2D elements use :ref:`Generate boundary elements <make_2dmesh_from_3d_page>` operation.
+
 The meshing algorithm is as follows.
 
 #. Lines of a Cartesian structured grid defined by :ref:`Body Fitting Parameters <cartesian_hyp_anchor>` hypothesis are intersected with the geometry boundary, thus nodes lying on the boundary are found. This step also allows finding out for each node of the Cartesian grid if it is inside or outside the geometry. 
index ccf0f7636e2705bd84fac632a1dd792dd5473963..d804e4cd79a17057a089a4e8fe4409e0f51f87aa 100644 (file)
@@ -117,8 +117,9 @@ General Preferences
 * **Python Dump**
 
   * **Historical python dump** - allows switching between *Historical* and *Snapshot* dump mode:
-  * In *Historical* mode, Python Dump script includes all commands performed by SMESH engine.
-  * In *Snapshot* mode, the commands relating to objects removed from the Study as well as the commands not influencing the current state of meshes are excluded from the script.
+
+    * In *Historical* mode, Python Dump script includes all commands performed by SMESH engine.
+    * In *Snapshot* mode, the commands relating to objects removed from the Study as well as the commands not influencing the current state of meshes are excluded from the script.
 
 .. _mesh_tab_preferences:
 
index 62c41498a968e592e820f912d31d2bb7b991b31a..3c9b7d1324a30465a255f83978fa8ae318022d61 100644 (file)
@@ -8,37 +8,37 @@ Salome provides a vast specter of mesh modification and transformation operation
 
 * :ref:`Add <adding_nodes_and_elements_page>` mesh elements from nodes to polyhedrons at an arbitrary place in the mesh.
 * :ref:`Add quadratic <adding_quadratic_elements_page>` mesh elements from quadratic segments to quadratic hexahedrons at an arbitrary place in the mesh.
-* :ref:`Remove <removing_nodes_and_elements_page>` any existin" mesh elements and nodes.
+* :ref:`Remove <removing_nodes_and_elements_page>` any existing mesh elements and nodes.
+* :ref:`Convert linear mesh to quadratic <convert_to_from_quadratic_mesh_page>`, or vice versa.
+* :ref:`Generate boundary elements <make_2dmesh_from_3d_page>`.
 * :ref:`Translate <translation_page>` in the indicated direction the mesh or some of its elements.
 * :ref:`Rotate <rotation_page>` by the indicated axis and angle the mesh or some of its elements.
 * :ref:`Scale <scale_page>` the mesh or some of its elements.
 * :ref:`Mirror <symmetry_page>` the mesh through a point, a vector or a plane of symmetry.
 * :ref:`double_nodes_page`. Duplication of nodes can be useful to emulate a crack in the model.
-* Unite meshes by :ref:`sewing <sewing_meshes_page>` free borders, border to side or side elements.
 * :ref:`Merge Nodes<merging_nodes_page>` coincident within the indicated tolerance.
 * :ref:`Merge Elements <merging_elements_page>` based on the same nodes.
+* Create an :ref:`extrusion <extrusion_page>` along a vector or by normal to a discretized surface.
+* Create an :ref:`extrusion along a path <extrusion_along_path_page>`.
+* Create elements by :ref:`revolution <revolution_page>` of the selected nodes and elements.
 * :ref:`Move Nodes <mesh_through_point_page>` to an arbitrary location with consequent transformation of all adjacent elements.
+* :ref:`Change orientation <changing_orientation_of_elements_page>` of the selected elements.
+* :ref:`Orient faces <reorient_faces_page>` by several means.
+* Unite meshes by :ref:`sewing <sewing_meshes_page>` free borders, border to side or side elements.
 * :ref:`Invert an edge <diagonal_inversion_of_elements_page>` between neighboring triangles.
 * :ref:`Unite two triangles <uniting_two_triangles_page>`.
 * :ref:`Unite several adjacent triangles <uniting_set_of_triangles_page>`.
-* :ref:`Change orientation <changing_orientation_of_elements_page>` of the selected elements.
-* :ref:`Orient faces <reorient_faces_page>` by several means.
 * :ref:`Cut a quadrangle <cutting_quadrangles_page>` into two triangles.
 * :ref:`Split <split_to_tetra_page>` volumic elements into tetrahedra or prisms.
 * :ref:`Split bi-quadratic <split_biquad_to_linear_page>` elements into linear ones without creation of additional nodes.
 * :ref:`Smooth <smoothing_page>` elements, reducung distortions in them by adjusting the locations of nodes.
-* Create an :ref:`extrusion <extrusion_page>` along a vector or by normal to a discretized surface.
-* Create an :ref:`extrusion along a path <extrusion_along_path_page>`.
-* Create elements by :ref:`revolution <revolution_page>` of the selected nodes and elements.
 * Apply :ref:`pattern mapping <pattern_mapping_page>`.
-* :ref:`Convert linear mesh to quadratic <convert_to_from_quadratic_mesh_page>`, or vice versa.
-* :ref:`Generate boundary elements <make_2dmesh_from_3d_page>`.
 * :ref:`generate_flat_elements_page`.
 * :ref:`cut_mesh_by_plane_page`.
 
 
 .. note::
-       It is possible to :ref:`modify the mesh <edit_anchor>` of a lower dimension before generation of the mesh of a higher dimension.
+       You can use these operations to :ref:`modify the mesh <edit_anchor>` of a lower dimension before generation of the mesh of a higher dimension.
 
 .. note::
        It is possible to use the variables defined in the SALOME **NoteBook** to specify the numerical parameters used for modification of any object.
index 4880d0746cc6feeccfd14b6e9456343a780be76f..b20b7cf8ef3e1b613450ed5576441577d4fde7a6 100644 (file)
@@ -33,7 +33,7 @@
 
 // ============================================================
 /*!
- * \brief Base class for elements of not contained in the mesh
+ * \brief Base class for elements not contained in the mesh
  */
 // ============================================================
 
index a6d61e8496bf5570fa4ae783b67a4cc62534a6b4..48d25afb5abfab665e54f53b71377ac9d64e92e0 100644 (file)
@@ -513,9 +513,10 @@ void SMDS_NodeFactory::SetShapeDim( int shapeID, int dim )
 
 SMDS_ElementChunk::SMDS_ElementChunk( SMDS_ElementFactory* factory, int id0 ):
   myFactory( factory ),
-  my1stID( id0 ),
-  myMinSubID( std::numeric_limits<int>::max() ),
-  myMaxSubID( 0 )
+  my1stID( id0 )//,
+  //mySubIDSet( 0 )
+  // myMinSubID( std::numeric_limits<int>::max() ),
+  // myMaxSubID( 0 )
 {
   if ( !myFactory )
     return;
@@ -665,7 +666,7 @@ int SMDS_ElementChunk::GetShapeID( const SMDS_MeshElement* e ) const
 
 void SMDS_ElementChunk::SetShapeID( const SMDS_MeshElement* e, int shapeID ) const
 {
-  const size_t nbRanges = mySubIDRanges.Size();
+  //const size_t nbRanges = mySubIDRanges.Size();
 
   SMDS_ElementChunk* me = const_cast<SMDS_ElementChunk*>( this );
   int oldShapeID = me->mySubIDRanges.SetValue( Index( e ), shapeID );
@@ -678,24 +679,24 @@ void SMDS_ElementChunk::SetShapeID( const SMDS_MeshElement* e, int shapeID ) con
       uv[1] = 0.;
     }
   // update min/max
-  if (( nbRanges > mySubIDRanges.Size() ) &&
-      ( myMinSubID == oldShapeID || myMaxSubID == oldShapeID ))
-  {
-    me->myMinSubID = ( std::numeric_limits<int>::max() );
-    me->myMaxSubID = 0;
-    TSubIDRangeSet::set_iterator it;
-    for ( it = mySubIDRanges.mySet.begin(); it < mySubIDRanges.mySet.end(); ++it )
-      if ( it->myValue > 0 )
-      {
-        me->myMinSubID = std::min( myMinSubID, it->myValue );
-        me->myMaxSubID = std::max( myMaxSubID, it->myValue );
-      }
-  }
-  else if ( shapeID > 0 )
-  {
-    me->myMinSubID = std::min( myMinSubID, shapeID );
-    me->myMaxSubID = std::max( myMaxSubID, shapeID );
-  }
+  // if (( nbRanges > mySubIDRanges.Size() ) &&
+  //     ( myMinSubID == oldShapeID || myMaxSubID == oldShapeID ))
+  // {
+  //   me->myMinSubID = ( std::numeric_limits<int>::max() );
+  //   me->myMaxSubID = 0;
+  //   TSubIDRangeSet::set_iterator it;
+  //   for ( it = mySubIDRanges.mySet.begin(); it < mySubIDRanges.mySet.end(); ++it )
+  //     if ( it->myValue > 0 )
+  //     {
+  //       me->myMinSubID = std::min( myMinSubID, it->myValue );
+  //       me->myMaxSubID = std::max( myMaxSubID, it->myValue );
+  //     }
+  // }
+  // else if ( shapeID > 0 )
+  // {
+  //   me->myMinSubID = std::min( myMinSubID, shapeID );
+  //   me->myMaxSubID = std::max( myMaxSubID, shapeID );
+  // }
 }
 
 //================================================================================
@@ -850,7 +851,7 @@ void SMDS_ElementChunk::Dump() const
 {
   std::cout << "1stID: " << my1stID << std::endl;
 
-  std::cout << "SubID min/max: " << myMinSubID << ", " << myMaxSubID << std::endl;
+  //std::cout << "SubID min/max: " << myMinSubID << ", " << myMaxSubID << std::endl;
   std::cout << "SubIDRanges: " << mySubIDRanges.Size() << " ";
   {
     TSubIDRangeSet::set_iterator i = mySubIDRanges.mySet.begin();
index 18c3d9461dbccbb79e893ee88fa71916b6d3938e..5fb6b3b4a1c05c353e0d9842c882657339d6e712 100644 (file)
@@ -108,8 +108,12 @@ public:
   //! Return an iterator on all element assigned to a given shape.
   //  nbElemsToReturn is used to optimize by stopping the iteration as soon as
   //  all elements assigned to the shape encountered.
+  //  sm1stElem is used to quickly find the first chunk holding elements of the shape;
+  //  it must have smallest ID between elements on the shape
   template< class ElemIterator >
-  boost::shared_ptr< ElemIterator > GetShapeIterator( int shapeID, size_t nbElemsToReturn );
+  boost::shared_ptr< ElemIterator > GetShapeIterator( int                     shapeID,
+                                                      size_t                  nbElemsToReturn,
+                                                      const SMDS_MeshElement* sm1stElem );
 
   //! Mark the element as non-used
   void Free( const SMDS_MeshElement* );
@@ -231,9 +235,9 @@ struct _RangeSet
   {
     bool isFound = false;
 
-    if ( sizeof( attr_t ) == sizeof( int ) && theMinValue )
-      if ( theValue < *theMinValue || theValue > *theMaxValue )
-        return isFound;
+    // if ( sizeof( attr_t ) == sizeof( int ) && theMinValue )
+    //   if ( theValue < *theMinValue || theValue > *theMaxValue )
+    //     return isFound;
 
     for ( set_iterator it = mySet.begin(); it < mySet.end(); ++it )
     {
@@ -354,6 +358,7 @@ typedef _RangeSet< _UsedRange >    TUsedRangeSet;
 typedef boost::dynamic_bitset<>    TBitSet;
 //typedef float                       TParam;
 typedef double                     TParam;
+//typedef std::unordered_set<int>    TSubIDSet;
 
 //------------------------------------------------------------------------------------
 /*!
@@ -369,8 +374,9 @@ class SMDS_ElementChunk
   TBitSet              myMarkedSet;   // mark some elements
   TUsedRangeSet        myUsedRanges;  // ranges of used/unused elements
   TSubIDRangeSet       mySubIDRanges; // ranges of elements on the same sub-shape
-  int                  myMinSubID;    // min sub-shape ID
-  int                  myMaxSubID;    // max sub-shape ID
+  //TSubIDSet*           mySubIDSet;    // set of sub-shape IDs
+  // int                  myMinSubID;    // min sub-shape ID
+  // int                  myMaxSubID;    // max sub-shape ID
   std::vector<TParam>  myPositions;   // UV parameters on shape: 2*param_t per an element
 
 public:
@@ -412,7 +418,7 @@ public:
 
   //! Return ranges of elements assigned to sub-shapes and min/max of sub-shape IDs
   const TSubIDRangeSet& GetSubIDRangesMinMax( int& min, int& max ) const
-  { min = myMinSubID; max = myMaxSubID; return mySubIDRanges; }
+  { /*min = myMinSubID; max = myMaxSubID;*/ return mySubIDRanges; }
 
   //! Minimize allocated memory
   void Compact();
@@ -469,11 +475,12 @@ struct _ChunkIterator : public ELEM_ITERATOR
                   get_rangeset_fun          theGetRangeSetFun,
                   attr_type                 theAttrValue,
                   SMDS_MeshElement::Filter* theFilter,
-                  size_t                    theNbElemsToReturn = -1):
+                  size_t                    theNbElemsToReturn = -1,
+                  int                       theChunkIndex = 0):
     myElement( 0 ),
     myRangeIndex( 0 ),
     myChunks( theChunks ),
-    myChunkIndex( -1 ),
+    myChunkIndex( theChunkIndex-1 ),
     myGetRangeSetFun( theGetRangeSetFun ),
     myValue( theAttrValue ),
     myFilter( theFilter ),
@@ -552,14 +559,18 @@ SMDS_ElementFactory::GetIterator( SMDS_MeshElement::Filter* filter,
 
 template< class ElemIterator >
 boost::shared_ptr< ElemIterator >
-SMDS_ElementFactory::GetShapeIterator( int shapeID, size_t nbElemsToReturn )
+SMDS_ElementFactory::GetShapeIterator( int                     shapeID,
+                                       size_t                  nbElemsToReturn,
+                                       const SMDS_MeshElement* sm1stElem )
 {
+  int iChunk = sm1stElem ? (( sm1stElem->GetID() - 1 ) / ChunkSize()) : 0;
   typedef _ChunkIterator< ElemIterator, TSubIDRangeSet > TChuckIterator;
   return boost::make_shared< TChuckIterator >( myChunks,
                                                & SMDS_ElementChunk::GetSubIDRangesMinMax,
                                                /*shapeID=*/shapeID,
                                                new SMDS_MeshElement::NonNullFilter(),
-                                               nbElemsToReturn );
+                                               nbElemsToReturn,
+                                               iChunk );
 }
 
 #endif
index 091359044d87e49642cf0594fbf2db958f7244fd..fd4dc82072244a398d7d40e717924918f8aaf3be 100644 (file)
@@ -37,7 +37,8 @@
 SMDS_ElementHolder::SMDS_ElementHolder( const SMDS_Mesh* mesh )
   : myMesh( const_cast< SMDS_Mesh* >( mesh ))
 {
-  myPtrInMesh = myMesh->myElemHolders.insert( this ).first;
+  if ( myMesh )
+    myPtrInMesh = myMesh->myElemHolders.insert( this ).first;
 }
 
 //=======================================================================
@@ -47,7 +48,8 @@ SMDS_ElementHolder::SMDS_ElementHolder( const SMDS_Mesh* mesh )
 
 SMDS_ElementHolder::~SMDS_ElementHolder()
 {
-  myMesh->myElemHolders.erase( myPtrInMesh );
+  if ( myMesh )
+    myMesh->myElemHolders.erase( myPtrInMesh );
 }
 
 //=======================================================================
index 790ff1bb3f72420abe69fad9ddf4e08845ce2c53..a117394b97b6184a957ae21c9622fc836441c2ef 100644 (file)
@@ -1611,14 +1611,18 @@ SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
                                              myInfo.NbVolumes());
 }
 
-SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int                  shapeID,
+                                                   size_t               nbElemsToReturn,
+                                                   const SMDS_MeshNode* sm1stNode) const
 {
-  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
+  return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn, sm1stNode );
 }
 
-SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int                     shapeID,
+                                                      size_t                  nbElemsToReturn,
+                                                      const SMDS_MeshElement* sm1stElem) const
 {
-  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
+  return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn, sm1stElem );
 }
 
 ///////////////////////////////////////////////////////////////////////////////
index e81735e44bab581ea7814238190f96468ba4899e..2661253aa4e5ded64dfd842278cce3cd596d58ce 100644 (file)
@@ -66,8 +66,12 @@ public:
   virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const;
   virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const;
 
-  virtual SMDS_NodeIteratorPtr shapeNodesIterator   (int shapeID, size_t nbElemsToReturn=-1) const;
-  virtual SMDS_ElemIteratorPtr shapeElementsIterator(int shapeID, size_t nbElemsToReturn=-1) const;
+  virtual SMDS_NodeIteratorPtr shapeNodesIterator   (int                  shapeID,
+                                                     size_t               nbElemsToReturn=-1,
+                                                     const SMDS_MeshNode* sm1stNode=0) const;
+  virtual SMDS_ElemIteratorPtr shapeElementsIterator(int                     shapeID,
+                                                     size_t                  nbElemsToReturn=-1,
+                                                     const SMDS_MeshElement* sm1stElem=0) const;
 
   SMDSAbs_ElementType GetElementType( const int id, const bool iselem ) const;
 
index 4a086e3b7073fc8d84be84192fe8c158b8302076..26c9ec1287225d59a1c242ff9f876e8f9b9a33c6 100644 (file)
 //
 #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)
+  : SMDS_ElementHolder( parent )
 {
   myParent = parent;
   myIndex = index;
   myNbElements = 0;
   myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
 }
 
 //================================================================================
@@ -84,6 +118,9 @@ void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * elem)
 
     elem->setShapeID( myIndex );
     myNbElements++;
+
+    // remember element with smallest ID to optimize iteration on them
+    add( elem );
   }
 }
 
@@ -102,6 +139,11 @@ bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * elem )
   {
     elem->setShapeID( 0 );
     myNbElements--;
+
+    const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
+    if ( elem1st == elem )
+      elem1st = 0;
+
     return true;
   }
   return false;
@@ -126,6 +168,9 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
     }
     N->setShapeID( myIndex );
     myNbNodes++;
+
+    // remember node with smallest ID to optimize iteration on them
+    add( N );
   }
 }
 
@@ -144,6 +189,11 @@ bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N)
   {
     N->setShapeID( 0 );
     myNbNodes--;
+
+    const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
+    if ( node1st == N )
+      node1st = 0;
+
     return true;
   }
   return false;
@@ -185,49 +235,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 +308,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 == 1 )
+  {
+    return boost::make_shared< EArrayIterator >( elem1st, elem1st+1 );
+  }
+
+  return myParent->shapeElementsIterator( myIndex, myNbElements, *elem1st );
 }
 
 //=======================================================================
@@ -314,7 +327,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 == 1 )
+  {
+    return boost::make_shared< NArrayIterator >( node1st, node1st+1 );
+  }
+
+  return myParent->shapeNodesIterator( myIndex, myNbNodes, *node1st );
 }
 
 //=======================================================================
@@ -438,6 +458,7 @@ void SMESHDS_SubMesh::Clear()
 
   myNbElements = 0;
   myNbNodes = 0;
+  my1stElemNode[0] = my1stElemNode[1] = 0;
   if ( NbSubMeshes() > 0 )
   {
     SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
@@ -447,3 +468,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;
+}
index 2caffb10b15b8e91a117f79f85abfaf3701feee2..f25ebfe9de4efa87a89ec6013ebc0c53c25c5625 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "SMESH_SMESHDS.hxx"
 
+#include "SMDS_ElementHolder.hxx"
 #include "SMDS_Mesh.hxx"
 #include <vector>
 
@@ -42,7 +43,7 @@ typedef boost::shared_ptr< SMESHDS_SubMeshIterator > SMESHDS_SubMeshIteratorPtr;
 
 class SMESHDS_Mesh;
 
-class SMESHDS_EXPORT SMESHDS_SubMesh
+class SMESHDS_EXPORT SMESHDS_SubMesh : public SMDS_ElementHolder
 {
  public:
   SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index);
@@ -55,8 +56,6 @@ class SMESHDS_EXPORT SMESHDS_SubMesh
   virtual bool RemoveElement(const SMDS_MeshElement * ME); // ret true if ME was in
   virtual void AddNode(const SMDS_MeshNode * ME);
   virtual bool RemoveNode(const SMDS_MeshNode * ME);       // ret true if ME was in
-  //virtual const SMDS_MeshElement* GetElement( size_t idInShape ) const;
-  //virtual const SMDS_MeshNode*    GetNode   ( size_t idInShape ) const;
 
   // if IsComplexSubmesh()
   void AddSubMesh( const SMESHDS_SubMesh* theSubMesh );
@@ -80,13 +79,21 @@ class SMESHDS_EXPORT SMESHDS_SubMesh
   SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); }
   int           GetID()     const { return myIndex; }
 
+ protected: // methods of SMDS_ElementHolder
+
+  virtual SMDS_ElemIteratorPtr getElements();
+  virtual void tmpClear();
+  virtual void add( const SMDS_MeshElement* element );
+  virtual void compact() {}
+
  private:
 
-  int             myIndex;
-  int             myNbElements;
-  int             myNbNodes;
-  SMESHDS_Mesh *  myParent;
-  TSubMeshSet     mySubMeshes;
+  int                     myIndex;
+  int                     myNbElements;
+  int                     myNbNodes;
+  const SMDS_MeshElement* my1stElemNode[2]; // elem and node with least ID, to optimize iteration
+  SMESHDS_Mesh *          myParent;
+  TSubMeshSet             mySubMeshes;
 
 };
 #endif
index 147d8dd9cd7b839156ed410c1611559b1483d893..c21f7f008ba408af21c3b087b52d14db343e6b87 100644 (file)
@@ -2189,10 +2189,11 @@ class Mesh(metaclass = MeshMeta):
                 fields: list of GEOM fields defined on the shape to mesh.
                 geomAssocFields: each character of this string means a need to export a 
                         corresponding field; correspondence between fields and characters is following:
-                        - 'v' stands for "_vertices _" field;
-                        - 'e' stands for "_edges _" field;
-                        - 'f' stands for "_faces _" field;
-                        - 's' stands for "_solids _" field.
+
+                        - 'v' stands for "_vertices_" field;
+                        - 'e' stands for "_edges_" field;
+                        - 'f' stands for "_faces_" field;
+                        - 's' stands for "_solids_" field.
         """
         # process positional arguments
         #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility