+ return myPredicate && myPredicate->IsSatisfy( elem->GetID() );
+}
+
+//================================================================================
+namespace // Iterator
+{
+ struct TIterator : public SMDS_ElemIterator
+ {
+ 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 ),
+ myTotalNb( totalNb ),
+ myFoundElems( foundElems ),
+ myFoundElemsOK( foundElemsOK )
+ {
+ myFoundElemsOK = false;
+ next();
+ }
+ ~TIterator()
+ {
+ if ( !myFoundElemsOK )
+ clearVector( myFoundElems );
+ }
+ virtual bool more()
+ {
+ return myNextElem;
+ }
+ virtual const SMDS_MeshElement* next()
+ {
+ const SMDS_MeshElement* res = 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
+ {
+ virtual bool more() { return false; }
+ virtual const SMDS_MeshElement* next() { return 0; }
+ };