From 9388a801df469f59fb0c16d41351b36e7b63089e Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 6 Dec 2006 15:53:25 +0000 Subject: [PATCH] PAL13473 (Build repetitive mesh): 1) add methods to track non hierarchical dependencies between submeshes 2) preview a case that an algo can be not assigned because a shape mismatches algo's expectations 3) fix pb that algo state can not change at MODIF_HYP event --- src/SMESH/SMESH_subMesh.cxx | 240 +++++++++++++++++++++++++++++++----- 1 file changed, 209 insertions(+), 31 deletions(-) diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 215eb1534..d47ab027c 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -28,6 +28,8 @@ using namespace std; #include "SMESH_subMesh.hxx" + +#include "SMESH_subMeshEventListener.hxx" #include "SMESH_Gen.hxx" #include "SMESH_Mesh.hxx" #include "SMESH_Hypothesis.hxx" @@ -532,8 +534,8 @@ SMESH_Hypothesis::Hypothesis_Status return SMESH_Hypothesis::HYP_OK; } - SMESH_Gen* gen =_father->GetGen(); -// bool ret = false; + SMESH_Gen* gen =_father->GetGen(); + SMESH_Algo* algo = 0; int oldAlgoState = _algoState; bool modifiedHyp = false; // if set to true, force event MODIF_ALGO_STATE // in ComputeStateEngine @@ -653,7 +655,7 @@ SMESH_Hypothesis::Hypothesis_Status } // Serve Propagation of 1D hypothesis else // event == REMOVE_ALGO { - SMESH_Algo* algo = dynamic_cast (anHyp); + algo = dynamic_cast (anHyp); if (!algo->NeedDescretBoundary()) { // clean all mesh in the tree of the current submesh; @@ -682,10 +684,14 @@ SMESH_Hypothesis::Hypothesis_Status case ADD_HYP: break; case ADD_ALGO: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if (algo->CheckHypothesis((*_father),_subShape, aux_ret)) SetAlgoState(HYP_OK); + else if ( algo->IsStatusFatal( aux_ret )) { + _meshDS->RemoveHypothesis(_subShape, anHyp); + ret = aux_ret; + } else SetAlgoState(MISSING_HYP); break; @@ -697,7 +703,7 @@ SMESH_Hypothesis::Hypothesis_Status case ADD_FATHER_HYP: break; case ADD_FATHER_ALGO: { // Algo just added in father - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo == anHyp ) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret)) @@ -710,7 +716,7 @@ SMESH_Hypothesis::Hypothesis_Status case REMOVE_FATHER_HYP: break; case REMOVE_FATHER_ALGO: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if (algo) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) @@ -732,7 +738,7 @@ SMESH_Hypothesis::Hypothesis_Status switch (event) { case ADD_HYP: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, ret )) SetAlgoState(HYP_OK); @@ -746,10 +752,14 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_ALGO: { //already existing algo : on father ? - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status SetAlgoState(HYP_OK); + else if ( algo->IsStatusFatal( aux_ret )) { + _meshDS->RemoveHypothesis(_subShape, anHyp); + ret = aux_ret; + } else SetAlgoState(MISSING_HYP); break; @@ -757,7 +767,7 @@ SMESH_Hypothesis::Hypothesis_Status case REMOVE_HYP: break; case REMOVE_ALGO: { // perhaps a father algo applies ? - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if (algo == NULL) // no more algo applying on subShape... { SetAlgoState(NO_ALGO); @@ -772,16 +782,16 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_FATHER_HYP: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) SetAlgoState(HYP_OK); else SetAlgoState(MISSING_HYP); - } break; + } case ADD_FATHER_ALGO: { // new father algo - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT( algo ); if ( algo == anHyp ) { if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) @@ -794,7 +804,7 @@ SMESH_Hypothesis::Hypothesis_Status case REMOVE_FATHER_HYP: // nothing to do break; case REMOVE_FATHER_ALGO: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if (algo == NULL) // no more applying algo on father { SetAlgoState(NO_ALGO); @@ -820,7 +830,7 @@ SMESH_Hypothesis::Hypothesis_Status switch (event) { case ADD_HYP: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if (!algo->CheckHypothesis((*_father),_subShape, ret )) { @@ -843,7 +853,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_ALGO: { //already existing algo : on father ? - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { // check if algo changes SMESH_HypoFilter f; @@ -860,7 +870,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case REMOVE_HYP: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) SetAlgoState(HYP_OK); @@ -870,7 +880,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case REMOVE_ALGO: { // perhaps a father algo applies ? - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if (algo == NULL) // no more algo applying on subShape... { SetAlgoState(NO_ALGO); @@ -888,7 +898,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_FATHER_HYP: { // new father hypothesis ? - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { @@ -900,7 +910,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case ADD_FATHER_ALGO: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if ( algo == anHyp ) { // a new algo on father if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { // check if algo changes @@ -919,7 +929,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case REMOVE_FATHER_HYP: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); ASSERT(algo); if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) { // is there the same local hyp or maybe a new father algo applied? @@ -931,7 +941,7 @@ SMESH_Hypothesis::Hypothesis_Status break; } case REMOVE_FATHER_ALGO: { - SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape); + algo = gen->GetAlgo((*_father), _subShape); if (algo == NULL) // no more applying algo on father { SetAlgoState(NO_ALGO); @@ -961,7 +971,16 @@ SMESH_Hypothesis::Hypothesis_Status break; } - if ((_algoState != oldAlgoState) || modifiedHyp) + if ( _algoState != oldAlgoState ) + { + if (_algoState == HYP_OK ) + algo->SetEventListener( this ); + if ( oldAlgoState == HYP_OK ) + DeleteOwnListeners(); + } + NotifyListenersOnEvent( event, ALGO_EVENT, anHyp ); + + if (_algoState != oldAlgoState || modifiedHyp) ComputeStateEngine(MODIF_ALGO_STATE); return ret; @@ -1187,6 +1206,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) SMESH_Algo *algo = 0; bool ret = true; SMESH_Hypothesis::Hypothesis_Status hyp_status; + algo_state oldAlgoState = (algo_state) GetAlgoState(); switch (_computeState) { @@ -1201,10 +1221,16 @@ bool SMESH_subMesh::ComputeStateEngine(int event) algo = gen->GetAlgo((*_father), _subShape); if (algo && !algo->NeedDescretBoundary()) CleanDependsOn(); // clean sub-meshes with event CLEAN - if (event == MODIF_ALGO_STATE && _algoState == HYP_OK) + if (algo) { - _computeState = READY_TO_COMPUTE; + ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); + if (ret) + _computeState = READY_TO_COMPUTE; } + if ( _computeState == READY_TO_COMPUTE ) + SetAlgoState(HYP_OK); + else + SetAlgoState(MISSING_HYP); break; case COMPUTE: // nothing to do break; @@ -1239,14 +1265,16 @@ bool SMESH_subMesh::ComputeStateEngine(int event) algo = gen->GetAlgo((*_father), _subShape); if (algo && !algo->NeedDescretBoundary()) CleanDependsOn(); // clean sub-meshes with event CLEAN - if (event == MODIF_HYP) - break; // nothing else to do when MODIF_HYP _computeState = NOT_READY; if (algo) { ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); - if (ret) + if (ret) { + SetAlgoState(HYP_OK); // it might be KO if BAD_PARAM_VALUE _computeState = READY_TO_COMPUTE; + } + else + SetAlgoState(MISSING_HYP); } break; case COMPUTE: @@ -1258,6 +1286,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event) { MESSAGE("***** verify compute state *****"); _computeState = NOT_READY; + SetAlgoState(MISSING_HYP); break; } // check submeshes needed @@ -1290,6 +1319,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) if (!ret) { MESSAGE("problem in algo execution: failed to compute"); + // release ALGO from responsibilty of partially built mesh + RemoveSubMeshElementsAndNodes(); _computeState = FAILED_TO_COMPUTE; if (!algo->NeedDescretBoundary()) UpdateSubMeshState( FAILED_TO_COMPUTE ); @@ -1325,6 +1356,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (ret) _computeState = READY_TO_COMPUTE; + else + SetAlgoState(MISSING_HYP); } break; case SUBMESH_COMPUTED: // nothing to do @@ -1371,6 +1404,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event) ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); if (ret) _computeState = READY_TO_COMPUTE; + else + SetAlgoState(MISSING_HYP); } break; case SUBMESH_COMPUTED: // nothing to do @@ -1456,6 +1491,15 @@ bool SMESH_subMesh::ComputeStateEngine(int event) break; } + if ( _algoState != oldAlgoState ) + { + if (_algoState == HYP_OK && algo ) + algo->SetEventListener( this ); + if ( oldAlgoState == HYP_OK ) + DeleteOwnListeners(); + } + NotifyListenersOnEvent( event, COMPUTE_EVENT ); + //SCRUTE(_computeState); return ret; } @@ -1624,11 +1668,9 @@ bool SMESH_subMesh::IsMeshComputed() const TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type ); for ( ; exp.More(); exp.Next() ) { - SMESHDS_SubMesh * subMeshDS = _meshDS->MeshElements( exp.Current() ); - if ( subMeshDS != NULL && - (subMeshDS->GetElements()->more() || subMeshDS->GetNodes()->more())) { + SMESHDS_SubMesh * smDS = _meshDS->MeshElements( exp.Current() ); + if ( smDS && ( smDS->NbElements() || smDS->NbNodes())) return true; - } } } else @@ -1751,3 +1793,139 @@ SMESH_Hypothesis::Hypothesis_Status } return SMESH_Hypothesis::HYP_OK; } + +//================================================================================ +/*! + * \brief Sets an event listener and its data to a submesh + * \param listener - the listener to store + * \param data - the listener data to store + * \param where - the submesh to store the listener and it's data + * \param deleteListener - if true then the listener will be deleted as + * it is removed from where submesh + * + * It remembers the submesh where it puts the listener in order to delete + * them when HYP_OK algo_state is lost + * After being set, event listener is notified on each event of where submesh. + */ +//================================================================================ + +void SMESH_subMesh::SetEventListener(EventListener* listener, + EventListenerData* data, + SMESH_subMesh* where) +{ + if ( listener && where ) { + where->SetEventListener( listener, data ); + myOwnListeners.push_back( make_pair( where, listener )); + } +} + +//================================================================================ +/*! + * \brief Sets an event listener and its data to a submesh + * \param listener - the listener to store + * \param data - the listener data to store + * + * After being set, event listener is notified on each event of a submesh. + */ +//================================================================================ + +void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data) +{ + myEventListeners.insert( make_pair( listener, data )); +} + +//================================================================================ +/*! + * \brief Return an event listener data + * \param listener - the listener whose data is + * \retval EventListenerData* - found data, maybe NULL + */ +//================================================================================ + +EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const +{ + map< EventListener*, EventListenerData* >::const_iterator l_d = + myEventListeners.find( listener ); + if ( l_d != myEventListeners.end() ) + return l_d->second; + return 0; +} + +//================================================================================ +/*! + * \brief Notify stored event listeners on the occured 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 data - listener data stored in the subMesh + * \param hyp - hypothesis, if eventType is algo_event + */ +//================================================================================ + +void SMESH_subMesh::NotifyListenersOnEvent( const int event, + const event_type eventType, + SMESH_Hypothesis* hyp) +{ + map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin(); + for ( ; l_d != myEventListeners.end(); ++l_d ) + l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp ); +} + +//================================================================================ +/*! + * \brief Unregister the listener and delete listener's data + * \param listener - the event listener + */ +//================================================================================ + +void SMESH_subMesh::DeleteEventListener(EventListener* listener) +{ + map< EventListener*, EventListenerData* >::iterator l_d = + myEventListeners.find( listener ); + if ( l_d != myEventListeners.end() ) { + delete l_d->first; + delete l_d->second; + myEventListeners.erase( l_d ); + } +} + +//================================================================================ +/*! + * \brief Delete event listeners depending on algo of this submesh + */ +//================================================================================ + +void SMESH_subMesh::DeleteOwnListeners() +{ + list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l; + for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l) + sm_l->first->DeleteEventListener( sm_l->second ); + myOwnListeners.clear(); +} + +//================================================================================ +/*! + * \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 data - listener data stored in the subMesh + * \param hyp - hypothesis, if eventType is algo_event + * + * The base implementation translates CLEAN event to the subMesh + * stored in listener data + */ +//================================================================================ + +void SMESH_subMeshEventListener::ProcessEvent(const int event, + const int eventType, + SMESH_subMesh* subMesh, + EventListenerData* data, + SMESH_Hypothesis* /*hyp*/) +{ + if ( event == SMESH_subMesh::CLEAN && eventType == SMESH_subMesh::COMPUTE_EVENT ) + if ( data && !data->mySubMeshes.empty() ) { + ASSERT( data->mySubMeshes.front() != subMesh ); + data->mySubMeshes.front()->ComputeStateEngine( event ); + } +}