//
#include "SMESHDS_GroupOnFilter.hxx"
-#include "SMESHDS_Mesh.hxx"
#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
#include <numeric>
#include <limits>
bool SMESHDS_GroupOnFilter::Contains (const int theID)
{
- return myPredicate ? myPredicate->IsSatisfy( theID ) : false;
+ return myPredicate && myPredicate->IsSatisfy( theID );
}
//================================================================================
bool SMESHDS_GroupOnFilter::Contains (const SMDS_MeshElement* elem)
{
- return myPredicate ? myPredicate->IsSatisfy( elem->GetID() ) : false;
+ return myPredicate && myPredicate->IsSatisfy( elem->GetID() );
}
//================================================================================
{
struct TIterator : public SMDS_ElemIterator
{
- SMESH_PredicatePtr myPredicate;
- SMDS_ElemIteratorPtr myElemIt;
- const SMDS_MeshElement* myNextElem;
- size_t myNbToFind, myNbFound;
- TIterator( const SMESH_PredicatePtr& filter,
- SMDS_ElemIteratorPtr& elems,
- size_t nbToFind):
+ SMESH_PredicatePtr myPredicate;
+ SMDS_ElemIteratorPtr myElemIt;
+ const SMDS_MeshElement* myNextElem;
+ size_t myNbToFind, myNbFound, myTotalNb;
+ vector< const SMDS_MeshElement*>& myFoundElems;
+ bool & myFoundElemsOK;
+
+ TIterator( const SMESH_PredicatePtr& filter,
+ SMDS_ElemIteratorPtr& elems,
+ size_t nbToFind,
+ size_t totalNb,
+ vector< const SMDS_MeshElement*>& foundElems,
+ bool & foundElemsOK):
myPredicate( filter ),
myElemIt( elems ),
myNextElem( 0 ),
myNbToFind( nbToFind ),
- myNbFound( 0 )
+ myNbFound( 0 ),
+ myTotalNb( totalNb ),
+ myFoundElems( foundElems ),
+ myFoundElemsOK( foundElemsOK )
{
+ myFoundElemsOK = false;
next();
}
+ ~TIterator()
+ {
+ if ( !myFoundElemsOK )
+ clearVector( myFoundElems );
+ }
virtual bool more()
{
return myNextElem;
myNbFound += bool( res );
myNextElem = 0;
if ( myNbFound < myNbToFind )
+ {
while ( myElemIt->more() && !myNextElem )
{
myNextElem = myElemIt->next();
if ( !myPredicate->IsSatisfy( myNextElem->GetID() ))
myNextElem = 0;
}
+ if ( myNextElem )
+ myFoundElems.push_back( myNextElem );
+ else
+ keepOrClearElemVec();
+ }
+ else
+ {
+ keepOrClearElemVec();
+ }
return res;
}
+ void keepOrClearElemVec()
+ {
+ if ( myNbFound == myTotalNb )
+ {
+ myFoundElemsOK = false; // all elems are OK, no need to keep them
+ }
+ else
+ {
+ // nb of bytes used for myFoundElems
+ size_t vecMemSize = myFoundElems.size() * sizeof( SMDS_MeshElement* ) / sizeof(char);
+ size_t aMB = 1024 * 1024;
+ if ( vecMemSize < aMB )
+ {
+ myFoundElemsOK = true; // < 1 MB - do not clear
+ }
+ else
+ {
+ int freeRamMB = SMDS_Mesh::CheckMemory( /*doNotRaise=*/true );
+ if ( freeRamMB < 0 )
+ myFoundElemsOK = true; // hope it's OK
+ else
+ myFoundElemsOK = ( freeRamMB * aMB > 10 * vecMemSize );
+ }
+ }
+ if ( !myFoundElemsOK )
+ clearVector( myFoundElems );
+ }
};
struct TEmptyIterator : public SMDS_ElemIterator
SMDS_ElemIteratorPtr SMESHDS_GroupOnFilter::GetElements() const
{
size_t nbToFind = std::numeric_limits<size_t>::max();
+ size_t totalNb = GetMesh()->GetMeshInfo().NbElements( GetType() );
- SMDS_ElemIteratorPtr elemIt;
+ SMDS_ElemIteratorPtr elemIt; // iterator on all elements to initialize TIterator
if ( myPredicate )
{
myPredicate->SetMesh( GetMesh() ); // hope myPredicate updates self here if necessary
elemIt = GetMesh()->elementsIterator( GetType() );
if ( IsUpToDate() )
{
+ if ( myElementsOK )
+ return SMDS_ElemIteratorPtr( new SMDS_ElementVectorIterator( myElements.begin(),
+ myElements.end() ));
nbToFind = Extent();
- if ( nbToFind == GetMesh()->GetMeshInfo().NbElements( GetType() ))
+ if ( nbToFind == totalNb )
return elemIt; // all elements are OK
for ( size_t i = 0; i < myNbElemToSkip; ++i )
elemIt->next(); // skip w/o check
{
elemIt = SMDS_ElemIteratorPtr( new TEmptyIterator );
}
- return SMDS_ElemIteratorPtr ( new TIterator( myPredicate, elemIt, nbToFind ));
+
+ // the iterator fills myElements if all elements are checked
+ SMESHDS_GroupOnFilter* me = const_cast<SMESHDS_GroupOnFilter*>( this );
+ return SMDS_ElemIteratorPtr
+ ( new TIterator( myPredicate, elemIt, nbToFind, totalNb, me->myElements, me->myElementsOK ));
}
//================================================================================
if ( changed && myMeshModifTime != 0 )
--myMeshModifTime;
if ( changed ) {
+ clearVector( myElements );
+ myElementsOK = false;
myNbElemToSkip = 0;
myMeshInfo.assign( SMDSEntity_Last, 0 );
}
std::vector< int > GetMeshInfo() const;
template< typename IDTYPE >
- int GetElementIds( IDTYPE* ids ) const
+ int GetElementIds( IDTYPE* ids ) const
{
return getElementIds( (void*)ids, sizeof(IDTYPE));
}
const SMDS_MeshElement* setNbElemToSkip( SMDS_ElemIteratorPtr& elIt );
int getElementIds( void* ids, size_t idSize ) const;
+ // We use two ways of optimaization:
+ // 1) The case of little free memory. Remember nb of KO elements (myNbElemToSkip)
+ // to skip before the first OK element. As well remember total nb of OK
+ // elements (myMeshInfo) to stop iteration as all OK elements are found.
+ // 2) The case of enough free memory. Remember all OK elements (myElements).
+
SMESH_PredicatePtr myPredicate;
std::vector< int > myMeshInfo;
+ std::vector< const SMDS_MeshElement*> myElements;
+ bool myElementsOK;
size_t myMeshModifTime; // when myMeshInfo was updated
int myPredicateTic;
size_t myNbElemToSkip;