Salome HOME
PAL13473 (Build repetitive mesh):
authoreap <eap@opencascade.com>
Wed, 6 Dec 2006 15:53:25 +0000 (15:53 +0000)
committereap <eap@opencascade.com>
Wed, 6 Dec 2006 15:53:25 +0000 (15:53 +0000)
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

index 215eb1534e6740fb12adc8c98725bfef60b3d714..d47ab027c4118b938f50ac8d9aff9e875b809cfc 100644 (file)
@@ -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<SMESH_Algo*> (anHyp);
+      algo = dynamic_cast<SMESH_Algo*> (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 );
+    }
+}