X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=728e4bae6596667d0c44b5fcde82a7a74f4df583;hb=59566e03c4763710021ff8bd81f8e60cc806cb66;hp=7c9cba60ff66d9ac8dee4bcae61db7eae66d316f;hpb=358f8ddd54e7ed553eecc22ca665575e4019e3a0;p=modules%2Fsmesh.git diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 7c9cba60f..728e4bae6 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -44,20 +44,34 @@ #include #include #include -#include #include #include -#include -#include #include #include #include +#include +#include -#include +#include #include using namespace std; +//============================================================================= +/*! + * \brief Allocate some memory at construction and release it at destruction. + * Is used to be able to continue working after mesh generation breaks due to + * lack of memory + */ +//============================================================================= + +struct MemoryReserve +{ + char* myBuf; + MemoryReserve(): myBuf( new char[1024*1024*2] ){} + ~MemoryReserve() { delete [] myBuf; } +}; + //============================================================================= /*! * default constructor: @@ -172,6 +186,19 @@ void SMESH_subMesh::SetIsAlwaysComputed(bool isAlCo) ComputeStateEngine( CHECK_COMPUTE_STATE ); } +//======================================================================= +/*! + * \brief Return true if no mesh entities is bound to the submesh + */ +//======================================================================= + +bool SMESH_subMesh::IsEmpty() const +{ + if (SMESHDS_SubMesh * subMeshDS = ((SMESH_subMesh*)this)->GetSubMeshDS()) + return (!subMeshDS->GetNodes()->more() && !subMeshDS->GetElements()->more()); + return true; +} + //======================================================================= //function : IsMeshComputed //purpose : check if _subMeshDS contains mesh elements @@ -397,10 +424,12 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() case TopAbs_SOLID: { //MESSAGE("solid"); - for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); - exp.Next()) - { - InsertDependence(exp.Current()); + if(_father->HasShapeToMesh()) { + for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); + exp.Next()) + { + InsertDependence(exp.Current()); + } } break; } @@ -482,10 +511,14 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons { int aHypDim = theHypothesis->GetDim(); int aShapeDim = SMESH_Gen::GetShapeDim(_subShape); + if (aHypDim == 3 && aShapeDim == 3) { + // check case of open shell + //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed()) + if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape)) + return false; + } if ( aHypDim <= aShapeDim ) return true; -// if ( aHypDim < aShapeDim ) -// return ( _father->IsMainShape( _subShape )); return false; } @@ -559,13 +592,18 @@ SMESH_Hypothesis::Hypothesis_Status return SMESH_Hypothesis::HYP_OK; } // 0D hypothesis - else if ( _algoState == HYP_OK ) { // update default _algoState - _algoState = NO_ALGO; - algo = gen->GetAlgo(*_father, _subShape); - if ( algo ) { - _algoState = MISSING_HYP; - if ( algo->CheckHypothesis(*_father,_subShape, aux_ret)) - _algoState = HYP_OK; + else if ( _algoState == HYP_OK ) { + // update default _algoState + if ( event != REMOVE_FATHER_ALGO ) + { + _algoState = NO_ALGO; + algo = gen->GetAlgo(*_father, _subShape); + if ( algo ) { + _algoState = MISSING_HYP; + if ( event == REMOVE_FATHER_HYP || + algo->CheckHypothesis(*_father,_subShape, aux_ret)) + _algoState = HYP_OK; + } } } } @@ -582,7 +620,7 @@ SMESH_Hypothesis::Hypothesis_Status // ------------------------------------------- algo = static_cast< SMESH_Algo* >( anHyp ); if ( !_father->HasShapeToMesh() && algo->NeedShape() ) - return SMESH_Hypothesis::HYP_BAD_GEOMETRY; + return SMESH_Hypothesis::HYP_NEED_SHAPE; // ---------------------- // check mesh conformity // ---------------------- @@ -603,49 +641,6 @@ SMESH_Hypothesis::Hypothesis_Status if ( !meshDS->AddHypothesis(_subShape, anHyp)) return SMESH_Hypothesis::HYP_ALREADY_EXIST; - - // Serve Propagation of 1D hypothesis - // NOTE: it is possible to re-implement Propagation using EventListener - if (event == ADD_HYP) { - bool isPropagationOk = true; - bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 ); - - if ( isPropagationHyp ) { - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current())) { - if (!_father->BuildPropagationChain(exp.Current())) { - isPropagationOk = false; - } - } - } - } - else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current())) { - TopoDS_Shape aMainEdge; - if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) { - isPropagationOk = _father->RebuildPropagationChains(); - } else if (_father->IsPropagationHypothesis(exp.Current())) { - isPropagationOk = _father->BuildPropagationChain(exp.Current()); - } else { - } - } - } - } else { - } - - if ( isPropagationOk ) { - if ( isPropagationHyp ) - return ret; // nothing more to do for "Propagation" hypothesis - } - else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) { - ret = SMESH_Hypothesis::HYP_CONCURENT; - } - } // Serve Propagation of 1D hypothesis } // -------------------------- @@ -656,45 +651,7 @@ SMESH_Hypothesis::Hypothesis_Status if (!meshDS->RemoveHypothesis(_subShape, anHyp)) return SMESH_Hypothesis::HYP_OK; // nothing changes - // Serve Propagation of 1D hypothesis - // NOTE: it is possible to re-implement Propagation using EventListener - if (event == REMOVE_HYP) - { - bool isPropagationOk = true; - SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" )); - bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape ); - - if ( isPropagationHyp ) - { - TopExp_Explorer exp (_subShape, TopAbs_EDGE); - TopTools_MapOfShape aMap; - for (; exp.More(); exp.Next()) { - if (aMap.Add(exp.Current()) && - !_father->GetHypothesis( exp.Current(), propagFilter, true )) { - // no more Propagation on the current edge - if (!_father->RemovePropagationChain(exp.Current())) { - return SMESH_Hypothesis::HYP_UNKNOWN_FATAL; - } - } - } - // rebuild propagation chains, because removing one - // chain can resolve concurention, existing before - isPropagationOk = _father->RebuildPropagationChains(); - } - else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated - { - isPropagationOk = _father->RebuildPropagationChains(); - } - - if ( isPropagationOk ) { - if ( isPropagationHyp ) - return ret; // nothing more to do for "Propagation" hypothesis - } - else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) { - ret = SMESH_Hypothesis::HYP_CONCURENT; - } - } // Serve Propagation of 1D hypothesis - else // event == REMOVE_ALGO + if (event == REMOVE_ALGO) { algo = dynamic_cast (anHyp); if (!algo->NeedDescretBoundary()) @@ -705,6 +662,7 @@ SMESH_Hypothesis::Hypothesis_Status CleanDependants(); ComputeStateEngine( CLEAN ); CleanDependsOn(); + ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE ); } } } @@ -1024,11 +982,13 @@ SMESH_Hypothesis::Hypothesis_Status TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape )); for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) { if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() )) - if ( !upperAlgo->NeedDescretBoundary() ) + if ( !upperAlgo->NeedDescretBoundary() && !upperAlgo->SupportSubmeshes()) ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO; } // is algo hiding? - if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) { + if ( ret == SMESH_Hypothesis::HYP_OK && + !algo->NeedDescretBoundary() && + !algo->SupportSubmeshes()) { map::reverse_iterator i_sm = _mapDepend.rbegin(); for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm ) if ( gen->GetAlgo( *_father, i_sm->second->_subShape )) @@ -1045,6 +1005,7 @@ SMESH_Hypothesis::Hypothesis_Status if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO DeleteOwnListeners(); + SetIsAlwaysComputed( false ); if (_subShape.ShapeType() == TopAbs_VERTEX ) { // restore default states _algoState = HYP_OK; @@ -1134,7 +1095,7 @@ SMESH_Hypothesis::Hypothesis_Status SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK; //EAP: a wire (dim==1) should notify edges (dim==1) //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape); - if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc + //if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc { SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); while ( smIt->more() ) { @@ -1236,7 +1197,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh ) while (itn->more()) { const SMDS_MeshNode * node = itn->next(); //MESSAGE( " RM node: "<GetID()); - if ( node->NbInverseNodes() == 0 ) + if ( node->NbInverseElements() == 0 ) meshDS->RemoveFreeNode(node, subMeshDS); else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another meshDS->RemoveNode(node); @@ -1264,7 +1225,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event) _computeState = READY_TO_COMPUTE; SMESHDS_SubMesh* smDS = GetSubMeshDS(); if ( smDS && smDS->NbNodes() ) { - _computeState = COMPUTE_OK; + if ( event == CLEAN ) { + CleanDependants(); + cleanSubMesh( this ); + } + else + _computeState = COMPUTE_OK; } else if ( event == COMPUTE && !_alwaysComputed ) { const TopoDS_Vertex & V = TopoDS::Vertex( _subShape ); @@ -1350,22 +1316,29 @@ bool SMESH_subMesh::ComputeStateEngine(int event) SetAlgoState(MISSING_HYP); break; } + TopoDS_Shape shape = _subShape; // check submeshes needed if (_father->HasShapeToMesh() ) { - bool subComputed = SubMeshesComputed(); + bool subComputed = false; + if (!algo->OnlyUnaryInput()) + shape = GetCollection( gen, algo, subComputed ); + else + subComputed = SubMeshesComputed(); ret = ( algo->NeedDescretBoundary() ? subComputed : + algo->SupportSubmeshes() ? true : ( !subComputed || _father->IsNotConformAllowed() )); if (!ret) { _computeState = FAILED_TO_COMPUTE; if ( !algo->NeedDescretBoundary() ) _computeError = - SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,"Unexpected submesh",algo); + SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH, + "Unexpected computed submesh",algo); break; } } // compute - CleanDependants(); - RemoveSubMeshElementsAndNodes(); +// CleanDependants(); for "UseExisting_*D" algos +// RemoveSubMeshElementsAndNodes(); ret = false; _computeState = FAILED_TO_COMPUTE; _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); @@ -1374,43 +1347,54 @@ bool SMESH_subMesh::ComputeStateEngine(int event) OCC_CATCH_SIGNALS; #endif algo->InitComputeError(); + MemoryReserve aMemoryReserve; + SMDS_Mesh::CheckMemory(); if ( !_father->HasShapeToMesh() ) // no shape { SMESH_MesherHelper helper( *_father ); - helper.SetSubShape( _subShape ); + helper.SetSubShape( shape ); helper.SetElementsOnShape( true ); ret = algo->Compute(*_father, &helper ); } else { - if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput()) { - ret = ApplyToCollection( algo, GetCollection( gen, algo ) ); - break; - } - else { - ret = algo->Compute((*_father), _subShape); - } + ret = algo->Compute((*_father), shape); } - if ( !ret ) + if ( !ret && _computeError->IsOK() ) // algo can set _computeError of submesh _computeError = algo->GetComputeError(); } - catch (Standard_Failure& exc) { + catch ( std::bad_alloc& exc ) { + MESSAGE("std::bad_alloc thrown inside algo->Compute()"); + if ( _computeError ) { + _computeError->myName = COMPERR_MEMORY_PB; + //_computeError->myComment = exc.what(); + } + cleanSubMesh( this ); + throw exc; + } + catch ( Standard_OutOfMemory& exc ) { + MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()"); + if ( _computeError ) { + _computeError->myName = COMPERR_MEMORY_PB; + //_computeError->myComment = exc.what(); + } + cleanSubMesh( this ); + throw std::bad_alloc(); + } + catch (Standard_Failure& ex) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_OCC_EXCEPTION; - _computeError->myComment = exc.GetMessageString(); + _computeError->myComment += ex.DynamicType()->Name(); + if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) { + _computeError->myComment += ": "; + _computeError->myComment += ex.GetMessageString(); + } } catch ( SALOME_Exception& S_ex ) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_SLM_EXCEPTION; _computeError->myComment = S_ex.what(); } - catch ( std::bad_alloc& exc ) { - if ( _computeError ) { - _computeError->myName = COMPERR_MEMORY_PB; - _computeError->myComment = exc.what(); - } - throw exc; - } catch ( std::exception& exc ) { if ( !_computeError ) _computeError = SMESH_ComputeError::New(); _computeError->myName = COMPERR_STD_EXCEPTION; @@ -1422,28 +1406,24 @@ bool SMESH_subMesh::ComputeStateEngine(int event) else ret = false; } - if ( ret && _computeError && !_computeError->IsOK() ) { - ret = false; - } - if (ret) { // check if anything was built + if (ret && !_alwaysComputed && shape == _subShape) { // check if anything was built ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() )); } - if (!ret) + bool isComputeErrorSet = !CheckComputeError( algo, shape ); + if (!ret && !isComputeErrorSet) { // Set _computeError if ( !_computeError ) _computeError = SMESH_ComputeError::New(); if ( _computeError->IsOK() ) _computeError->myName = COMPERR_ALGO_FAILED; + _computeState = FAILED_TO_COMPUTE; } - else + if (ret) { _computeError.reset(); - UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } - if ( !algo->NeedDescretBoundary() ) - UpdateSubMeshState( ret ? COMPUTE_OK : FAILED_TO_COMPUTE ); - CheckComputeError( algo ); + UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED } break; case CLEAN: @@ -1534,6 +1514,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event) switch (event) { case MODIF_ALGO_STATE: + algo = gen->GetAlgo((*_father), _subShape); + if (algo && !algo->NeedDescretBoundary()) + CleanDependsOn(); // clean sub-meshes with event CLEAN if (_algoState == HYP_OK) _computeState = READY_TO_COMPUTE; else @@ -1584,53 +1567,80 @@ bool SMESH_subMesh::ComputeStateEngine(int event) //======================================================================= /*! - * \brief Update compute_state by _computeError + * \brief Update compute_state by _computeError and send proper events to + * dependent submeshes + * \retval bool - true if _computeError is NOT set */ //======================================================================= -bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo) +bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape) { - bool noErrors = ( !_computeError || _computeError->IsOK() ); - if ( !noErrors ) + bool noErrors = true; + + if ( !theShape.IsNull() ) { - if ( !_computeError->myAlgo ) - _computeError->myAlgo = theAlgo; - - // Show error - SMESH_Comment text; - text << theAlgo->GetName() << " failed on subshape " << _Id << " with error "; - if (_computeError->IsCommon() ) - text << _computeError->CommonName(); + // Check state of submeshes + if ( !theAlgo->NeedDescretBoundary()) + { + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); + while ( smIt->more() ) + if ( !smIt->next()->CheckComputeError( theAlgo )) + noErrors = false; + } + + // Check state of neighbours + if ( !theAlgo->OnlyUnaryInput() && + theShape.ShapeType() == TopAbs_COMPOUND && + !theShape.IsSame( _subShape )) + { + for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) { + SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() ); + if ( sm != this ) { + if ( !sm->CheckComputeError( theAlgo, sm->GetSubShape() )) + noErrors = false; + UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED + } + } + } + } + { + // Check my state + if ( !_computeError || _computeError->IsOK() ) + { + _computeState = COMPUTE_OK; + } else - text << _computeError->myName; - if ( _computeError->myComment.size() > 0 ) - text << " \"" << _computeError->myComment << "\""; + { + if ( !_computeError->myAlgo ) + _computeError->myAlgo = theAlgo; + + // Show error + SMESH_Comment text; + text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error "; + if (_computeError->IsCommon() ) + text << _computeError->CommonName(); + else + text << _computeError->myName; + if ( _computeError->myComment.size() > 0 ) + text << " \"" << _computeError->myComment << "\""; #ifdef _DEBUG_ - cout << text << endl; - // Show vertices location of a failed shape - cout << "Subshape vertices (first 10):" << endl; - TopTools_IndexedMapOfShape vMap; - TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap ); - for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) { - gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) ))); - cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl; - } + MESSAGE_BEGIN ( text ); + // Show vertices location of a failed shape + TopTools_IndexedMapOfShape vMap; + TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap ); + MESSAGE_ADD ( "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") ); + for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) { + gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) ))); + MESSAGE_ADD ( "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " " + << P.X() << " " << P.Y() << " " << P.Z() << " " ); + } #else - INFOS( text ); + INFOS( text ); #endif - _computeState = FAILED_TO_COMPUTE; - } - else - { - _computeState = COMPUTE_OK; - } - // Check state of submeshes - if ( !theAlgo->NeedDescretBoundary() /*&& theAlgo->OnlyUnaryInput()*/ ) { - SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false); - while ( smIt->more() ) - if ( !smIt->next()->CheckComputeError( theAlgo )) - noErrors = false; + _computeState = FAILED_TO_COMPUTE; + noErrors = false; + } } return noErrors; } @@ -1779,10 +1789,13 @@ void SMESH_subMesh::RemoveSubMeshElementsAndNodes() // meshed at once along with _subShape //======================================================================= -TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo) +TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, + SMESH_Algo* theAlgo, + bool & theSubComputed) { MESSAGE("SMESH_subMesh::GetCollection"); - ASSERT (!theAlgo->NeedDescretBoundary()); + + theSubComputed = SubMeshesComputed(); TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh(); @@ -1812,9 +1825,11 @@ TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlg else if ( subMesh->GetComputeState() == READY_TO_COMPUTE ) { SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S ); - if (anAlgo == theAlgo && - anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) + if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo + anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps aBuilder.Add( aCompound, S ); + if ( !subMesh->SubMeshesComputed() ) + theSubComputed = false; } } @@ -1929,8 +1944,9 @@ void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.find( listener ); if ( l_d != myEventListeners.end() ) { - if ( l_d->second && l_d->second->IsDeletable() ) - delete l_d->second; + EventListenerData* curData = l_d->second; + if ( curData && curData != data && curData->IsDeletable() ) + delete curData; l_d->second = data; } else @@ -2031,13 +2047,17 @@ void SMESH_subMeshEventListener::ProcessEvent(const int event, eventType == SMESH_subMesh::COMPUTE_EVENT) { ASSERT( data->mySubMeshes.front() != subMesh ); + list::iterator smIt = data->mySubMeshes.begin(); + list::iterator smEnd = data->mySubMeshes.end(); switch ( event ) { case SMESH_subMesh::CLEAN: - data->mySubMeshes.front()->ComputeStateEngine( event ); + for ( ; smIt != smEnd; ++ smIt) + (*smIt)->ComputeStateEngine( event ); break; case SMESH_subMesh::COMPUTE: if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK ) - data->mySubMeshes.front()->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED ); + for ( ; smIt != smEnd; ++ smIt) + (*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED ); break; default:; } @@ -2058,7 +2078,8 @@ namespace { SMESH_subMesh* prepend, SMESH_subMesh* append): myIt(subIt),myAppend(append) { - myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0; + myCur = prepend ? prepend : myIt->more() ? myIt->next() : append; + if ( myCur == append ) append = 0; } /// Return true if and only if there are other object in this iterator virtual bool more()