Salome HOME
PAL19272 CEA patch 4.1.1 / 3.2.9: problem with nodes or corners
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index ac208e3ffb5f11a7d25180bc7522187387b99111..030fe7c3662c85eece9866589cac856512c752eb 100644 (file)
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <TopExp.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Compound.hxx>
 #include <gp_Pnt.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Iterator.hxx>
 
 #include <Standard_OutOfMemory.hxx>
 #include <Standard_ErrorHandler.hxx>
@@ -985,6 +984,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;
@@ -1176,7 +1176,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh )
       while (itn->more()) {
         const SMDS_MeshNode * node = itn->next();
         //MESSAGE( " RM node: "<<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);
@@ -1204,7 +1204,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     _computeState = READY_TO_COMPUTE;
     SMESHDS_SubMesh* smDS = GetSubMeshDS();
     if ( smDS && smDS->NbNodes() ) {
-      _computeState = COMPUTE_OK;
+      if ( event == CLEAN ) // this occures for algo which !NeedDescretBoundary() (PAL19272)
+        cleanSubMesh( this );
+      else
+        _computeState = COMPUTE_OK;
     }
     else if ( event == COMPUTE && !_alwaysComputed ) {
       const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
@@ -1299,44 +1302,44 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
             _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);
+        TopoDS_Shape shape = _subShape;
         try {
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
           OCC_CATCH_SIGNALS;
 #endif
-          MemoryReserve aMemoryReserve;
           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);
+            if (!algo->OnlyUnaryInput()) {
+              shape = GetCollection( gen, algo );
             }
+            ret = algo->Compute((*_father), shape);
           }
           if ( !ret )
             _computeError = algo->GetComputeError();
         }
         catch ( std::bad_alloc& exc ) {
-          printf("std::bad_alloc\n");
+          printf("std::bad_alloc thrown inside algo->Compute()\n");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
             //_computeError->myComment = exc.what();
@@ -1345,7 +1348,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           throw exc;
         }
         catch ( Standard_OutOfMemory& exc ) {
-          printf("Standard_OutOfMemory\n");
+          printf("Standard_OutOfMemory thrown inside algo->Compute()\n");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
             //_computeError->myComment = exc.what();
@@ -1378,28 +1381,24 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             ret = false;
         }
-        if ( ret && _computeError && !_computeError->IsOK() ) {
-          ret = false;
-        }
         if (ret && !_alwaysComputed) { // 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:
@@ -1540,54 +1539,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 ))
+            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
-    TopTools_IndexedMapOfShape vMap;
-    TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
-    cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
-    for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
-      gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
-      cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
-      cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
-    }
+      cout << text << endl;
+      // Show vertices location of a failed shape
+      TopTools_IndexedMapOfShape vMap;
+      TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
+      cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
+      for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
+        gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
+        cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
+        cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
+      }
 #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;
 }
@@ -1739,7 +1764,6 @@ void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
 {
   MESSAGE("SMESH_subMesh::GetCollection");
-  ASSERT (!theAlgo->NeedDescretBoundary());
 
   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
 
@@ -1886,8 +1910,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 
@@ -1988,13 +2013,17 @@ void SMESH_subMeshEventListener::ProcessEvent(const int          event,
        eventType == SMESH_subMesh::COMPUTE_EVENT)
   {
     ASSERT( data->mySubMeshes.front() != subMesh );
+    list<SMESH_subMesh*>::iterator smIt = data->mySubMeshes.begin();
+    list<SMESH_subMesh*>::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:;
     }