Salome HOME
PR: synchro V6_main tag mergeto_V7_main_11Feb13
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index af4e614a8706ebb1f26b2a2500b10607ab893db9..1c03f3fc3e2c3f0381b36b24fae218ff37d9c5c5 100644 (file)
@@ -149,6 +149,17 @@ SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
  */
 //=============================================================================
 
+const SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() const
+{
+  return ((SMESH_subMesh*) this )->GetSubMeshDS();
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
 SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
 {
   if ( !GetSubMeshDS() ) {
@@ -253,11 +264,11 @@ bool SMESH_subMesh::IsMeshComputed() const
 
 //=============================================================================
 /*!
- *
+ * Return true if all sub-meshes have been meshed
  */
 //=============================================================================
 
-bool SMESH_subMesh::subMeshesComputed()
+bool SMESH_subMesh::SubMeshesComputed() const
 {
   int myDim = SMESH_Gen::GetShapeDim( _subShape );
   int dimToCheck = myDim - 1;
@@ -406,6 +417,10 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
       {
         insertDependence(exp.Current());
       }
+      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next())
+      {
+        insertDependence(exp.Current());
+      }
       break;
     }
   case TopAbs_COMPSOLID:
@@ -1118,7 +1133,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
  */
 //=============================================================================
 
-void SMESH_subMesh::setAlgoState(int state)
+void SMESH_subMesh::setAlgoState(algo_state state)
 {
   _algoState = state;
 }
@@ -1254,7 +1269,19 @@ static void cleanSubMesh( SMESH_subMesh * subMesh )
 
 bool SMESH_subMesh::ComputeStateEngine(int event)
 {
-  _computeError.reset();
+  switch ( event ) {
+  case MODIF_ALGO_STATE:
+  case COMPUTE:
+    //case COMPUTE_CANCELED:
+  case CLEAN:
+    //case SUBMESH_COMPUTED:
+    //case SUBMESH_RESTORED:
+    //case SUBMESH_LOADED:
+    //case MESH_ENTITY_REMOVED:
+    //case CHECK_COMPUTE_STATE:
+    _computeError.reset(); break;
+  default:;
+  }
 
   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
   //SCRUTE(_computeState);
@@ -1371,7 +1398,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           if (!algo->OnlyUnaryInput())
             shape = getCollection( gen, algo, subComputed );
           else
-            subComputed = subMeshesComputed();
+            subComputed = SubMeshesComputed();
           ret = ( algo->NeedDiscreteBoundary() ? subComputed :
                   algo->SupportSubmeshes() ? true :
                   ( !subComputed || _father->IsNotConformAllowed() ));
@@ -1447,9 +1474,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           }
         }
         catch ( SALOME_Exception& S_ex ) {
+          const int skipSalomeShift = 7; /* to skip "Salome " of
+                                            "Salome Exception" prefix returned
+                                            by SALOME_Exception::what() */
           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
           _computeError->myName    = COMPERR_SLM_EXCEPTION;
-          _computeError->myComment = S_ex.what();
+          _computeError->myComment = S_ex.what() + skipSalomeShift;
         }
         catch ( std::exception& exc ) {
           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
@@ -1462,16 +1492,18 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             ret = false;
         }
+        // check if an error reported on any sub-shape
+        bool isComputeErrorSet = !checkComputeError( algo, ret, shape );
+        // check if anything was built
         TopExp_Explorer subS(shape, _subShape.ShapeType());
-        if (ret) // check if anything was built
+        if (ret)
         {
           for (; ret && subS.More(); subS.Next())
             ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed();
         }
-        bool isComputeErrorSet = !checkComputeError( algo, shape );
+        // Set _computeError
         if (!ret && !isComputeErrorSet)
         {
-          // Set _computeError
           for (subS.ReInit(); subS.More(); subS.Next())
           {
             SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
@@ -1490,7 +1522,26 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         {
           _computeError.reset();
         }
-        updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+
+        // send event SUBMESH_COMPUTED
+        if ( ret ) {
+          if ( !algo->NeedDiscreteBoundary() )
+            // send SUBMESH_COMPUTED to dependants of all sub-meshes of shape
+            for (subS.ReInit(); subS.More(); subS.Next())
+            {
+              SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+              SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+              while ( smIt->more() ) {
+                sm = smIt->next();
+                if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX )
+                  sm->updateDependantsState( SUBMESH_COMPUTED );
+                else
+                  break;
+              }
+            }
+          else
+            updateDependantsState( SUBMESH_COMPUTED );
+        }
       }
       break;
 #ifdef WITH_SMESH_CANCEL_COMPUTE
@@ -1609,14 +1660,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       break;
     case COMPUTE:      // nothing to do
       break;
-#ifdef WITH_SMESH_CANCEL_COMPUTE
     case COMPUTE_CANCELED:
       {
         algo = GetAlgo();
         algo->CancelCompute();
       }
       break;
-#endif
     case CLEAN:
       cleanDependants(); // submeshes dependent on me should be cleaned as well
       removeSubMeshElementsAndNodes();
@@ -1725,7 +1774,9 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
  */
 //=======================================================================
 
-bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape)
+bool SMESH_subMesh::checkComputeError(SMESH_Algo*         theAlgo,
+                                      const bool          theComputeOK,
+                                      const TopoDS_Shape& theShape)
 {
   bool noErrors = true;
 
@@ -1736,7 +1787,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
     {
       SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
       while ( smIt->more() )
-        if ( !smIt->next()->checkComputeError( theAlgo ))
+        if ( !smIt->next()->checkComputeError( theAlgo, theComputeOK ))
           noErrors = false;
     }
 
@@ -1748,7 +1799,7 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
       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() ))
+          if ( !sm->checkComputeError( theAlgo, theComputeOK, sm->GetSubShape() ))
             noErrors = false;
           updateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
         }
@@ -1756,13 +1807,24 @@ bool SMESH_subMesh::checkComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
     }
   }
   {
-    // Check my state
+
+    // Set my _computeState
+
     if ( !_computeError || _computeError->IsOK() )
     {
       // no error description is set to this sub-mesh, check if any mesh is computed
       _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE;
+      if ( _computeState != COMPUTE_OK )
+      {
+        if ( _subShape.ShapeType() == TopAbs_EDGE &&
+             BRep_Tool::Degenerated( TopoDS::Edge( _subShape )) )
+          _computeState = COMPUTE_OK;
+        else if ( theComputeOK )
+          _computeError = SMESH_ComputeError::New(COMPERR_NO_MESH_ON_SHAPE,"",theAlgo);
+      }
     }
-    else
+
+    if ( _computeError && !_computeError->IsOK() )
     {
       if ( !_computeError->myAlgo )
         _computeError->myAlgo = theAlgo;
@@ -1822,9 +1884,7 @@ void SMESH_subMesh::updateDependantsState(const compute_event theEvent)
   for (; it.More(); it.Next())
   {
     const TopoDS_Shape& ancestor = it.Value();
-    SMESH_subMesh *aSubMesh =
-      _father->GetSubMeshContaining(ancestor);
-    if (aSubMesh)
+    if ( SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor))
       aSubMesh->ComputeStateEngine( theEvent );
   }
 }
@@ -1893,7 +1953,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
                                           SMESH_Algo* theAlgo,
                                           bool &      theSubComputed)
 {
-  theSubComputed = subMeshesComputed();
+  theSubComputed = SubMeshesComputed();
 
   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
 
@@ -1926,7 +1986,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
       if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
           anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
         aBuilder.Add( aCompound, S );
-      if ( !subMesh->subMeshesComputed() )
+      if ( !subMesh->SubMeshesComputed() )
         theSubComputed = false;
     }
   }
@@ -2049,7 +2109,8 @@ void SMESH_subMesh::SetEventListener(EventListener*     listener,
  */
 //================================================================================
 
-void SMESH_subMesh::setEventListener(EventListener* listener, EventListenerData* data)
+void SMESH_subMesh::setEventListener(EventListener*     listener,
+                                     EventListenerData* data)
 {
   map< EventListener*, EventListenerData* >::iterator l_d =
     _eventListeners.find( listener );
@@ -2059,8 +2120,21 @@ void SMESH_subMesh::setEventListener(EventListener* listener, EventListenerData*
       delete curData;
     l_d->second = data;
   }
-  else 
+  else
+  {
+    for ( l_d = _eventListeners.begin(); l_d != _eventListeners.end(); ++l_d )
+      if ( listener->GetName() == l_d->first->GetName() )
+      {
+        EventListenerData* curData = l_d->second;
+        if ( curData && curData != data && curData->IsDeletable() )
+          delete curData;
+        if ( l_d->first->IsDeletable() )
+          delete l_d->first;
+        _eventListeners.erase( l_d );
+        break;
+      }
     _eventListeners.insert( make_pair( listener, data ));
+  }
 }
 
 //================================================================================
@@ -2080,6 +2154,23 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener)
   return 0;
 }
 
+//================================================================================
+/*!
+ * \brief Return an event listener data
+ * \param listenerName - the listener name
+ * \retval EventListenerData* - found data, maybe NULL
+ */
+//================================================================================
+
+EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerName) const
+{
+  map< EventListener*, EventListenerData* >::const_iterator l_d = _eventListeners.begin();
+  for ( ; l_d != _eventListeners.end(); ++l_d )
+    if ( listenerName == l_d->first->GetName() )
+      return l_d->second;
+  return 0;
+}
+
 //================================================================================
 /*!
  * \brief Notify stored event listeners on the occured event
@@ -2094,16 +2185,18 @@ void SMESH_subMesh::notifyListenersOnEvent( const int         event,
                                             SMESH_Hypothesis* hyp)
 {
   map< EventListener*, EventListenerData* >::iterator l_d = _eventListeners.begin();
-  for ( ; l_d != _eventListeners.end(); ++l_d )
+  for ( ; l_d != _eventListeners.end();  )
   {
-    std::pair< EventListener*, EventListenerData* > li_da = *l_d; /* copy to enable removal
-                                                                     of a listener from
-                                                                     _eventListeners by
-                                                                     its ProcessEvent() */
+    std::pair< EventListener*, EventListenerData* > li_da = *l_d++; /* copy to enable removal
+                                                                       of a listener from
+                                                                       _eventListeners by
+                                                                       its ProcessEvent() */
     if ( li_da.first->myBusySM.insert( this ).second )
     {
+      const size_t nbListenersBefore = _eventListeners.size();
       li_da.first->ProcessEvent( event, eventType, this, li_da.second, hyp );
-      li_da.first->myBusySM.erase( this );
+      if ( nbListenersBefore == _eventListeners.size() )
+        li_da.first->myBusySM.erase( this ); // a listener hopefully not removed
     }
   }
 }
@@ -2119,9 +2212,18 @@ void SMESH_subMesh::DeleteEventListener(EventListener* listener)
 {
   map< EventListener*, EventListenerData* >::iterator l_d =
     _eventListeners.find( listener );
-  if ( l_d != _eventListeners.end() ) {
-    if ( l_d->first  && l_d->first->IsDeletable() )  delete l_d->first;
-    if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second;
+  if ( l_d != _eventListeners.end() && l_d->first )
+  {
+    if ( l_d->second && l_d->second->IsDeletable() )
+    {
+      delete l_d->second;
+    }
+    l_d->first->myBusySM.erase( this );
+    if ( l_d->first->IsDeletable() )
+    {
+      l_d->first->BeforeDelete( this, l_d->second );
+      delete l_d->first;
+    }
     _eventListeners.erase( l_d );
   }
 }
@@ -2260,22 +2362,23 @@ namespace {
 //================================================================================
 
 SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf,
-                                                             const bool reverse)
+                                                             const bool reverse) const
 {
+  SMESH_subMesh *me = (SMESH_subMesh*) this;
   SMESH_subMesh *prepend=0, *append=0;
   if ( includeSelf ) {
-    if ( reverse ) prepend = this;
-    else            append = this;
+    if ( reverse ) prepend = me;
+    else            append = me;
   }
   typedef map < int, SMESH_subMesh * > TMap;
   if ( reverse )
   {
     return SMESH_subMeshIteratorPtr
-      ( new _Iterator( new SMDS_mapReverseIterator<TMap>( DependsOn() ), prepend, append ));
+      ( new _Iterator( new SMDS_mapReverseIterator<TMap>( me->DependsOn() ), prepend, append ));
   }
   {
     return SMESH_subMeshIteratorPtr
-      ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
+      ( new _Iterator( new SMDS_mapIterator<TMap>( me->DependsOn() ), prepend, append ));
   }
 }