From 3781c2c7d624bcb660e9e2ca4d6329f7f3aa0f53 Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 8 Aug 2018 16:55:53 +0300 Subject: [PATCH] Regression of SALOME_TESTS/Grids/smesh/3D_mesh_Extrusion_01/B8 Optimize iteration on sub-mesh elements + minor doc fix --- .../gui/SMESH/input/basic_meshing_algos.rst | 2 +- doc/salome/gui/SMESH/input/cartesian_algo.rst | 2 + .../gui/SMESH/input/mesh_preferences.rst | 5 +- .../gui/SMESH/input/modifying_meshes.rst | 20 +-- src/SMDS/SMDS_CellOfNodes.hxx | 2 +- src/SMDS/SMDS_ElementFactory.cxx | 47 +++--- src/SMDS/SMDS_ElementFactory.hxx | 33 ++-- src/SMDS/SMDS_ElementHolder.cxx | 6 +- src/SMDS/SMDS_Mesh.cxx | 12 +- src/SMDS/SMDS_Mesh.hxx | 8 +- src/SMESHDS/SMESHDS_SubMesh.cxx | 155 ++++++++++++------ src/SMESHDS/SMESHDS_SubMesh.hxx | 23 ++- src/SMESH_SWIG/smeshBuilder.py | 9 +- 13 files changed, 209 insertions(+), 115 deletions(-) diff --git a/doc/salome/gui/SMESH/input/basic_meshing_algos.rst b/doc/salome/gui/SMESH/input/basic_meshing_algos.rst index 9033c3104..692232fd1 100644 --- a/doc/salome/gui/SMESH/input/basic_meshing_algos.rst +++ b/doc/salome/gui/SMESH/input/basic_meshing_algos.rst @@ -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. diff --git a/doc/salome/gui/SMESH/input/cartesian_algo.rst b/doc/salome/gui/SMESH/input/cartesian_algo.rst index bde18de08..46605bbe4 100644 --- a/doc/salome/gui/SMESH/input/cartesian_algo.rst +++ b/doc/salome/gui/SMESH/input/cartesian_algo.rst @@ -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 ` operation. + The meshing algorithm is as follows. #. Lines of a Cartesian structured grid defined by :ref:`Body Fitting Parameters ` 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. diff --git a/doc/salome/gui/SMESH/input/mesh_preferences.rst b/doc/salome/gui/SMESH/input/mesh_preferences.rst index ccf0f7636..d804e4cd7 100644 --- a/doc/salome/gui/SMESH/input/mesh_preferences.rst +++ b/doc/salome/gui/SMESH/input/mesh_preferences.rst @@ -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: diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.rst b/doc/salome/gui/SMESH/input/modifying_meshes.rst index 62c41498a..3c9b7d132 100644 --- a/doc/salome/gui/SMESH/input/modifying_meshes.rst +++ b/doc/salome/gui/SMESH/input/modifying_meshes.rst @@ -8,37 +8,37 @@ Salome provides a vast specter of mesh modification and transformation operation * :ref:`Add ` mesh elements from nodes to polyhedrons at an arbitrary place in the mesh. * :ref:`Add quadratic ` mesh elements from quadratic segments to quadratic hexahedrons at an arbitrary place in the mesh. -* :ref:`Remove ` any existin" mesh elements and nodes. +* :ref:`Remove ` any existing mesh elements and nodes. +* :ref:`Convert linear mesh to quadratic `, or vice versa. +* :ref:`Generate boundary elements `. * :ref:`Translate ` in the indicated direction the mesh or some of its elements. * :ref:`Rotate ` by the indicated axis and angle the mesh or some of its elements. * :ref:`Scale ` the mesh or some of its elements. * :ref:`Mirror ` 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 ` free borders, border to side or side elements. * :ref:`Merge Nodes` coincident within the indicated tolerance. * :ref:`Merge Elements ` based on the same nodes. +* Create an :ref:`extrusion ` along a vector or by normal to a discretized surface. +* Create an :ref:`extrusion along a path `. +* Create elements by :ref:`revolution ` of the selected nodes and elements. * :ref:`Move Nodes ` to an arbitrary location with consequent transformation of all adjacent elements. +* :ref:`Change orientation ` of the selected elements. +* :ref:`Orient faces ` by several means. +* Unite meshes by :ref:`sewing ` free borders, border to side or side elements. * :ref:`Invert an edge ` between neighboring triangles. * :ref:`Unite two triangles `. * :ref:`Unite several adjacent triangles `. -* :ref:`Change orientation ` of the selected elements. -* :ref:`Orient faces ` by several means. * :ref:`Cut a quadrangle ` into two triangles. * :ref:`Split ` volumic elements into tetrahedra or prisms. * :ref:`Split bi-quadratic ` elements into linear ones without creation of additional nodes. * :ref:`Smooth ` elements, reducung distortions in them by adjusting the locations of nodes. -* Create an :ref:`extrusion ` along a vector or by normal to a discretized surface. -* Create an :ref:`extrusion along a path `. -* Create elements by :ref:`revolution ` of the selected nodes and elements. * Apply :ref:`pattern mapping `. -* :ref:`Convert linear mesh to quadratic `, or vice versa. -* :ref:`Generate boundary elements `. * :ref:`generate_flat_elements_page`. * :ref:`cut_mesh_by_plane_page`. .. note:: - It is possible to :ref:`modify the mesh ` of a lower dimension before generation of the mesh of a higher dimension. + You can use these operations to :ref:`modify the mesh ` 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. diff --git a/src/SMDS/SMDS_CellOfNodes.hxx b/src/SMDS/SMDS_CellOfNodes.hxx index 4880d0746..b20b7cf8e 100644 --- a/src/SMDS/SMDS_CellOfNodes.hxx +++ b/src/SMDS/SMDS_CellOfNodes.hxx @@ -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 */ // ============================================================ diff --git a/src/SMDS/SMDS_ElementFactory.cxx b/src/SMDS/SMDS_ElementFactory.cxx index a6d61e849..48d25afb5 100644 --- a/src/SMDS/SMDS_ElementFactory.cxx +++ b/src/SMDS/SMDS_ElementFactory.cxx @@ -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::max() ), - myMaxSubID( 0 ) + my1stID( id0 )//, + //mySubIDSet( 0 ) + // myMinSubID( std::numeric_limits::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( 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::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::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(); diff --git a/src/SMDS/SMDS_ElementFactory.hxx b/src/SMDS/SMDS_ElementFactory.hxx index 18c3d9461..5fb6b3b4a 100644 --- a/src/SMDS/SMDS_ElementFactory.hxx +++ b/src/SMDS/SMDS_ElementFactory.hxx @@ -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 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 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 diff --git a/src/SMDS/SMDS_ElementHolder.cxx b/src/SMDS/SMDS_ElementHolder.cxx index 091359044..fd4dc8207 100644 --- a/src/SMDS/SMDS_ElementHolder.cxx +++ b/src/SMDS/SMDS_ElementHolder.cxx @@ -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 ); } //======================================================================= diff --git a/src/SMDS/SMDS_Mesh.cxx b/src/SMDS/SMDS_Mesh.cxx index 790ff1bb3..a117394b9 100644 --- a/src/SMDS/SMDS_Mesh.cxx +++ b/src/SMDS/SMDS_Mesh.cxx @@ -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 ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/SMDS/SMDS_Mesh.hxx b/src/SMDS/SMDS_Mesh.hxx index e81735e44..2661253aa 100644 --- a/src/SMDS/SMDS_Mesh.hxx +++ b/src/SMDS/SMDS_Mesh.hxx @@ -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; diff --git a/src/SMESHDS/SMESHDS_SubMesh.cxx b/src/SMESHDS/SMESHDS_SubMesh.cxx index 4a086e3b7..26c9ec128 100644 --- a/src/SMESHDS/SMESHDS_SubMesh.cxx +++ b/src/SMESHDS/SMESHDS_SubMesh.cxx @@ -28,12 +28,44 @@ // #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 +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 @@ -41,11 +73,13 @@ //================================================================================ 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 MySetIterator : public SMDS_Iterator -{ -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; +} diff --git a/src/SMESHDS/SMESHDS_SubMesh.hxx b/src/SMESHDS/SMESHDS_SubMesh.hxx index 2caffb10b..f25ebfe9d 100644 --- a/src/SMESHDS/SMESHDS_SubMesh.hxx +++ b/src/SMESHDS/SMESHDS_SubMesh.hxx @@ -29,6 +29,7 @@ #include "SMESH_SMESHDS.hxx" +#include "SMDS_ElementHolder.hxx" #include "SMDS_Mesh.hxx" #include @@ -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 diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 147d8dd9c..c21f7f008 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -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 -- 2.30.2