X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH%2FSMESH_subMesh.cxx;h=ecfa286c1698578defb202cfaae2cea3e592f0d1;hp=128316dcf55c87817dbf3e556cb61bf02a660d35;hb=d9f4b53e489dd5857db264ede6acded7b076c9f1;hpb=0f9ed6f02c1e57730c871370ee2ec04a1f417593 diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 128316dcf..ecfa286c1 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -20,7 +20,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SMESH SMESH : implementaion of SMESH idl descriptions +// SMESH SMESH : implementation of SMESH idl descriptions // File : SMESH_subMesh.cxx // Author : Paul RASCLE, EDF // Module : SMESH @@ -38,10 +38,7 @@ #include "SMESH_MesherHelper.hxx" #include "SMESH_subMeshEventListener.hxx" -#include - #include "utilities.h" -#include "OpUtil.hxx" #include "Basics_Utils.hxx" #include @@ -63,6 +60,11 @@ using namespace std; +#ifdef _DEBUG_ +// enable printing algo + shape id + hypo used while meshing +//#define PRINT_WHO_COMPUTE_WHAT +#endif + //============================================================================= /*! * \brief Allocate some memory at construction and release it at destruction. @@ -107,6 +109,7 @@ SMESH_subMesh::SMESH_subMesh(int Id, } _computeCost = 0; // how costly is to compute this sub-mesh _realComputeCost = 0; + _allowedSubShapes = nullptr; } //============================================================================= @@ -198,7 +201,7 @@ SMESH_Algo* SMESH_subMesh::GetAlgo() const if ( !_algo ) { SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); - me->_algo = _father->GetGen()->GetAlgo( me ); + me->_algo = _father->GetGen()->GetAlgo( me, & me->_algoShape ); } return _algo; } @@ -268,6 +271,42 @@ bool SMESH_subMesh::IsMeshComputed() const return false; } +//================================================================================ +/*! + * \brief Check if any upper level sub-shape is not computed. + * Used to update a sub-mesh icon + */ +//================================================================================ + +bool SMESH_subMesh::IsComputedPartially() const +{ + SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(/*includeSelf=*/true, + /*SolidFirst=*/true); + bool allComputed = true; + TopAbs_ShapeEnum readyType = TopAbs_VERTEX; // max value + while ( smIt->more() && allComputed ) + { + SMESH_subMesh* sm = smIt->next(); + + if ( sm->GetSubShape().ShapeType() > readyType ) + break; // lower dimension -> stop + if ( sm->GetComputeState() != SMESH_subMesh::NOT_READY ) + readyType = sm->GetSubShape().ShapeType(); + + switch ( sm->GetComputeState() ) + { + case SMESH_subMesh::READY_TO_COMPUTE: + case SMESH_subMesh::FAILED_TO_COMPUTE: + allComputed = false;// sm->IsMeshComputed(); + break; + case SMESH_subMesh::NOT_READY: + case SMESH_subMesh::COMPUTE_OK: + continue; + } + } + return !allComputed; +} + //============================================================================= /*! * Return true if all sub-meshes have been meshed @@ -362,7 +401,7 @@ int SMESH_subMesh::computeCost() const */ //============================================================================= -const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() +const std::map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn() { if ( _dependenceAnalysed || !_father->HasShapeToMesh() ) return _mapDepend; @@ -488,7 +527,7 @@ const TopoDS_Shape & SMESH_subMesh::GetSubShape() const //======================================================================= //function : CanAddHypothesis //purpose : return true if theHypothesis can be attached to me: -// its dimention is checked +// its dimension is checked //======================================================================= bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const @@ -509,12 +548,25 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons } //======================================================================= -//function : IsApplicableHypotesis -//purpose : +//function : IsApplicableHypothesis +//purpose : check if this sub-mesh can be computed using a hypothesis //======================================================================= -bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis, - const TopAbs_ShapeEnum theShapeType) +bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis) const +{ + if ( !_father->HasShapeToMesh() && _subShape.ShapeType() == TopAbs_SOLID ) + return true; // true for the PseudoShape + + return IsApplicableHypothesis( theHypothesis, _subShape.ShapeType() ); +} + +//======================================================================= +//function : IsApplicableHypothesis +//purpose : compare shape type and hypothesis type +//======================================================================= + +bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis, + const TopAbs_ShapeEnum theShapeType) { if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO) { @@ -606,7 +658,7 @@ SMESH_Hypothesis::Hypothesis_Status bool modifiedHyp = (event == MODIF_HYP); // if set to true, force event MODIF_ALGO_STATE SMESH_Algo* algoRequiringCleaning = 0; - bool isApplicableHyp = IsApplicableHypotesis( anHyp ); + bool isApplicableHyp = IsApplicableHypothesis( anHyp ); if (event == ADD_ALGO || event == ADD_FATHER_ALGO) { @@ -628,7 +680,7 @@ SMESH_Hypothesis::Hypothesis_Status filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 )); filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 )); if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true )) - if ( !curAlgo->NeedDiscreteBoundary() ) + if ( !curAlgo->NeedDiscreteBoundary() && curAlgo != anHyp ) algoRequiringCleaning = curAlgo; } } @@ -862,7 +914,10 @@ SMESH_Hypothesis::Hypothesis_Status const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true ); if (prevAlgo && string( algo->GetName()) != prevAlgo->GetName()) - modifiedHyp = true; + { + oldAlgoState = NO_ALGO; // force setting event listener (#16648) + modifiedHyp = true; + } } else setAlgoState(MISSING_HYP); @@ -1056,7 +1111,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo) if ( !theAlgo ) return false; // Suppose that theAlgo is applicable to _subShape, do not check it here - //if ( !IsApplicableHypotesis( theAlgo )) return false; + //if ( !IsApplicableHypothesis( theAlgo )) return false; // check only algo that doesn't NeedDiscreteBoundary(): because mesh made // on a sub-shape will be ignored by theAlgo @@ -1272,25 +1327,24 @@ void SMESH_subMesh::DumpAlgoState(bool isMain) static void cleanSubMesh( SMESH_subMesh * subMesh ) { if (subMesh) { - if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) { + if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) + { SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS(); - SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); - while (ite->more()) { - const SMDS_MeshElement * elt = ite->next(); - //MESSAGE( " RM elt: "<GetID()<<" ( "<NbNodes()<<" )" ); - //meshDS->RemoveElement(elt); - meshDS->RemoveFreeElement(elt, 0); - } - - SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); - while (itn->more()) { - const SMDS_MeshNode * node = itn->next(); - //MESSAGE( " RM node: "<GetID()); - if ( node->NbInverseElements() == 0 ) - meshDS->RemoveFreeNode(node, 0); - else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another - meshDS->RemoveNode(node); - } + smIdType nbElems = subMeshDS->NbElements(); + if ( nbElems > 0 ) + for ( SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); ite->more(); ) + meshDS->RemoveFreeElement( ite->next(), subMeshDS ); + + smIdType nbNodes = subMeshDS->NbNodes(); + if ( nbNodes > 0 ) + for ( SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); itn->more() ; ) + { + const SMDS_MeshNode * node = itn->next(); + if ( node->NbInverseElements() == 0 ) + meshDS->RemoveFreeNode( node, subMeshDS ); + else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another + meshDS->RemoveNode( node ); + } subMeshDS->Clear(); } } @@ -1390,6 +1444,7 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) loadDependentMeshes(); ComputeSubMeshStateEngine( SUBMESH_LOADED ); //break; + // fall through case CHECK_COMPUTE_STATE: if ( IsMeshComputed() ) _computeState = COMPUTE_OK; @@ -1416,6 +1471,32 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) _computeState = READY_TO_COMPUTE; } break; + + case COMPUTE_NOGEOM: // no geometry; can be several algos + if ( !_father->HasShapeToMesh() ) + { + algo = GetAlgo(); // current algo + if ( algo ) + { + // apply algos in the order of increasing dimension + std::list< const SMESHDS_Hypothesis * > algos = _father->GetHypothesisList( _subShape ); + for ( int t = SMESHDS_Hypothesis::ALGO_1D; t <= SMESHDS_Hypothesis::ALGO_3D; ++t ) + { + std::list::iterator al = algos.begin(); + for ( ; al != algos.end(); ++al ) + if ( (*al)->GetType() == t ) + { + _algo = (SMESH_Algo*) *al; + _computeState = READY_TO_COMPUTE; + if ( !ComputeStateEngine( COMPUTE )) + break; + } + } + _algo = algo; // restore + } + break; + } + // fall through case COMPUTE: case COMPUTE_SUBMESH: { @@ -1435,11 +1516,14 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) if (_father->HasShapeToMesh() ) { bool subComputed = false, subFailed = false; if (!algo->OnlyUnaryInput()) { - if ( event == COMPUTE /*&& - ( algo->NeedDiscreteBoundary() || algo->SupportSubmeshes() )*/) - shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute()); - else - subComputed = SubMeshesComputed( & subFailed ); + // --- commented for bos#22320 to compute all sub-shapes at once if possible; + // --- in case COMPUTE_SUBMESH, set of sub-shapes is limited + // --- by calling SetAllowedSubShapes() + // if ( event == COMPUTE ) + // shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToComput; + // else + // subComputed = SubMeshesComputed( & subFailed ); + shape = getCollection( gen, algo, subComputed, subFailed, algo->SubMeshesToCompute()); } else { subComputed = SubMeshesComputed(); @@ -1499,7 +1583,6 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) MESSAGE("std::bad_alloc thrown inside algo->Compute()"); if ( _computeError ) { _computeError->myName = COMPERR_MEMORY_PB; - //_computeError->myComment = exc.what(); } cleanSubMesh( this ); throw exc; @@ -1508,7 +1591,6 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()"); if ( _computeError ) { _computeError->myName = COMPERR_MEMORY_PB; - //_computeError->myComment = exc.what(); } cleanSubMesh( this ); throw std::bad_alloc(); @@ -1549,7 +1631,7 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) ret = false; // check if anything was built TopExp_Explorer subS(shape, _subShape.ShapeType()); - if (ret) + if ( ret ) { for (; ret && subS.More(); subS.Next()) if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() && @@ -1557,10 +1639,28 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) !algo->isDegenerated( TopoDS::Edge( subS.Current() )))) ret = false; } +#ifdef PRINT_WHO_COMPUTE_WHAT + for (subS.ReInit(); subS.More(); subS.Next()) + { + const std::list & hyps = + _algo->GetUsedHypothesis( *_father, _subShape ); + SMESH_Comment hypStr; + if ( !hyps.empty() ) + { + hypStr << hyps.front()->GetName() << " "; + ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() ); + hypStr << " "; + } + cout << _father->GetSubMesh( subS.Current() )->GetId() + << " " << ( ret ? "OK" : "FAIL" ) + << " " << _algo->GetName() + << " " << hypStr << endl; + } +#endif // Set _computeError - if (!ret && !isComputeErrorSet) + if ( !ret && !isComputeErrorSet ) { - for (subS.ReInit(); subS.More(); subS.Next()) + for ( subS.ReInit(); subS.More(); subS.Next() ) { SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() ); if ( !sm->IsMeshComputed() ) @@ -1574,7 +1674,7 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) } } } - if (ret && _computeError && _computeError->myName != COMPERR_WARNING ) + if ( ret && _computeError && _computeError->myName != COMPERR_WARNING ) { _computeError.reset(); } @@ -1628,6 +1728,8 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) else updateDependantsState( SUBMESH_COMPUTED ); } + // let algo clear its data gathered while algo->Compute() + algo->CheckHypothesis((*_father), _subShape, hyp_status); } break; case COMPUTE_CANCELED: // nothing to do @@ -1662,6 +1764,7 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) loadDependentMeshes(); ComputeSubMeshStateEngine( SUBMESH_LOADED ); //break; + // fall through case CHECK_COMPUTE_STATE: if ( IsMeshComputed() ) _computeState = COMPUTE_OK; @@ -1687,10 +1790,12 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) break; case COMPUTE: // nothing to do break; + case COMPUTE_SUBMESH: // nothing to do + break; case COMPUTE_CANCELED: // nothing to do break; case CLEAN: - cleanDependants(); // clean sub-meshes, dependant on this one, with event CLEAN + cleanDependants(); // clean sub-meshes, dependent on this one, with event CLEAN removeSubMeshElementsAndNodes(); _computeState = NOT_READY; if ( _algoState == HYP_OK ) @@ -1811,7 +1916,7 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) bool ret = true; if (_subShape.ShapeType() == TopAbs_VERTEX) { - vector aVec(SMDSEntity_Last,0); + vector aVec(SMDSEntity_Last,0); aVec[SMDSEntity_Node] = 1; aResMap.insert(make_pair(this,aVec)); return ret; @@ -1838,7 +1943,7 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) SMESH_subMesh* sm = smIt->next(); int dim = SMESH_Gen::GetShapeDim( sm->GetSubShape() ); if (dim < dimToCheck) break; // the rest subMeshes are all of less dimension - const vector & nbs = aResMap[ sm ]; + const vector & nbs = aResMap[ sm ]; subMeshEvaluated = (std::accumulate( nbs.begin(), nbs.end(), 0 ) > 0 ); } if ( !subMeshEvaluated ) @@ -1848,7 +1953,7 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) if ( IsMeshComputed() ) { - vector & nbEntities = aResMap[ this ]; + vector & nbEntities = aResMap[ this ]; nbEntities.resize( SMDSEntity_Last, 0 ); if ( SMESHDS_SubMesh* sm = GetSubMeshDS() ) { @@ -1862,7 +1967,7 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) { ret = algo->Evaluate((*_father), _subShape, aResMap); } - aResMap.insert( make_pair( this,vector(0))); + aResMap.insert( make_pair( this,vector(0))); } return ret; @@ -2046,7 +2151,7 @@ void SMESH_subMesh::removeSubMeshElementsAndNodes() // meshed at once along with _subShape //======================================================================= -TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, +TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * /*theGen*/, SMESH_Algo* theAlgo, bool & theSubComputed, bool & theSubFailed, @@ -2060,8 +2165,9 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, return _subShape; const bool skipAuxHyps = false; - list aUsedHyp = + list usedHyps = theAlgo->GetUsedHypothesis( *_father, _subShape, skipAuxHyps ); // copy + std::list < TopoDS_Shape > assiShapes = theAlgo->GetAssignedShapes(); // put in a compound all shapes with the same hypothesis assigned // and a good ComputeState @@ -2079,6 +2185,8 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, const TopoDS_Shape& S = subMesh->_subShape; if ( S.ShapeType() != this->_subShape.ShapeType() ) continue; + if ( _allowedSubShapes && !_allowedSubShapes->IsEmpty() && !_allowedSubShapes->Contains( S )) + continue; if ( subMesh == this ) { aBuilder.Add( aCompound, S ); @@ -2088,7 +2196,9 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, { SMESH_Algo* anAlgo = subMesh->GetAlgo(); if (( anAlgo->IsSameName( *theAlgo )) && // same algo - ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == aUsedHyp )) // same hyps + ( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == usedHyps ) && // same hyps + ( anAlgo->GetAssignedShapes() == assiShapes ) && // on same sub-shapes + ( _algoShape == subMesh->_algoShape )) { aBuilder.Add( aCompound, S ); if ( !subMesh->SubMeshesComputed() ) @@ -2098,7 +2208,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen, } } - return aCompound; + return theSubs.size() == 1 ? theSubs[0]->GetSubShape() : aCompound; } //======================================================================= @@ -2131,16 +2241,14 @@ const SMESH_Hypothesis* SMESH_subMesh::getSimilarAttached(const TopoDS_Shape& } //======================================================================= -//function : CheckConcurentHypothesis +//function : CheckConcurrentHypothesis //purpose : check if there are several applicable hypothesis attached to // ancestors //======================================================================= SMESH_Hypothesis::Hypothesis_Status - SMESH_subMesh::CheckConcurentHypothesis (const int theHypType) + SMESH_subMesh::CheckConcurrentHypothesis (const int theHypType) { - MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis"); - // is there local hypothesis on me? if ( getSimilarAttached( _subShape, 0, theHypType ) ) return SMESH_Hypothesis::HYP_OK; @@ -2161,7 +2269,7 @@ SMESH_Hypothesis::Hypothesis_Status aPrevHyp = hyp; } else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp ) - return SMESH_Hypothesis::HYP_CONCURENT; + return SMESH_Hypothesis::HYP_CONCURRENT; else return SMESH_Hypothesis::HYP_OK; } @@ -2223,9 +2331,9 @@ void SMESH_subMesh::setEventListener(EventListener* listener, _eventListeners.find( listener ); if ( l_d != _eventListeners.end() ) { EventListenerData* curData = l_d->second; + l_d->second = data; if ( curData && curData != data && curData->IsDeletable() ) delete curData; - l_d->second = data; } else { @@ -2233,6 +2341,7 @@ void SMESH_subMesh::setEventListener(EventListener* listener, if ( listener->GetName() == l_d->first->GetName() ) { EventListenerData* curData = l_d->second; + l_d->second = 0; if ( curData && curData != data && curData->IsDeletable() ) delete curData; if ( l_d->first != listener && l_d->first->IsDeletable() ) @@ -2310,7 +2419,7 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerNam //================================================================================ /*! - * \brief Notify stored event listeners on the occured event + * \brief Notify stored event listeners on the occurred event * \param event - algo_event or compute_event itself * \param eventType - algo_event or compute_event * \param hyp - hypothesis, if eventType is algo_event @@ -2396,7 +2505,8 @@ void SMESH_subMesh::loadDependentMeshes() { list< OwnListenerData >::iterator d; for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d ) - if ( _father != d->mySubMesh->_father ) + if ( _father != d->mySubMesh->_father && + _father->FindMesh( d->myMeshID )) d->mySubMesh->_father->Load(); // map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin(); @@ -2416,7 +2526,7 @@ void SMESH_subMesh::loadDependentMeshes() * \brief Do something on a certain event * \param event - algo_event or compute_event itself * \param eventType - algo_event or compute_event - * \param subMesh - the submesh where the event occures + * \param subMesh - the submesh where the event occurs * \param data - listener data stored in the subMesh * \param hyp - hypothesis, if eventType is algo_event * @@ -2495,9 +2605,9 @@ namespace { //================================================================================ /*! - * \brief Return iterator on the submeshes this one depends on - * \param includeSelf - this submesh to be returned also - * \param reverse - if true, complex shape submeshes go first + * \brief Return iterator on the submeshes this one depends on + * \param includeSelf - this submesh to be returned also + * \param reverse - if true, complex shape submeshes go first */ //================================================================================ @@ -2538,8 +2648,13 @@ const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this ); me->_ancestors.reserve( ancShapes.Extent() ); + // assure that all sub-meshes exist + TopoDS_Shape mainShape = _father->GetShapeToMesh(); + if ( !mainShape.IsNull() ) + _father->GetSubMesh( mainShape )->DependsOn(); + TopTools_MapOfShape map; - + for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() ) if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() )) if ( map.Add( it.Value() ))