Salome HOME
Update copyright
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index d93b598a50336f83786885dd011ef5ac68206e7b..da001a0bfcdd554ea8129de21fec3be5a0dacbea 100644 (file)
@@ -1,24 +1,25 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2011  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
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
 //
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_subMesh.cxx
 //  Author : Paul RASCLE, EDF
@@ -39,6 +40,7 @@
 
 #include "utilities.h"
 #include "OpUtil.hxx"
+#include "Basics_Utils.hxx"
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
@@ -263,7 +265,7 @@ bool SMESH_subMesh::SubMeshesComputed()
       break; // the rest subMeshes are all of less dimension
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-                      (ds && ( ds->NbNodes() || ds->NbElements() )));
+                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes()  )));
     if (!computeOk)
     {
       int type = ss.ShapeType();
@@ -370,23 +372,24 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_COMPOUND:
     {
       //MESSAGE("compound");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next())
       {
+        if ( BRep_Tool::IsClosed(exp.Current() ))
           InsertDependence(exp.Current());      //only shell not in solid
+        else
+          for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next())
+            InsertDependence(expF.Current());    // issue 0020959: HEXA_3D fails on shell
+
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -394,9 +397,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
     }
   case TopAbs_COMPSOLID:
     {
-                //MESSAGE("compsolid");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-           exp.Next())
+      //MESSAGE("compsolid");
+      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -405,8 +407,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_SHELL:
     {
       //MESSAGE("shell");
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -415,8 +416,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_WIRE:
     {
       //MESSAGE("wire");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -426,8 +426,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
     {
       //MESSAGE("solid");
       if(_father->HasShapeToMesh()) {
-        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-             exp.Next())
+        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
         {
           InsertDependence(exp.Current());
         }
@@ -437,8 +436,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_FACE:
     {
       //MESSAGE("face");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -447,11 +445,10 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_EDGE:
     {
       //MESSAGE("edge");
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
       {
-                        InsertDependence(exp.Current());
-                      }
+        InsertDependence(exp.Current());
+      }
       break;
     }
   case TopAbs_VERTEX:
@@ -1003,9 +1000,12 @@ SMESH_Hypothesis::Hypothesis_Status
     if ( ret == SMESH_Hypothesis::HYP_OK &&
          !algo->NeedDescretBoundary()    &&
          !algo->SupportSubmeshes()) {
+      TopoDS_Shape algoAssignedTo, otherAssignedTo;
+      gen->GetAlgo( *_father, _subShape, &algoAssignedTo );
       map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
       for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
-        if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
+        if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) &&
+             SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
           ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
     }
   }
@@ -1288,6 +1288,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       break;
     case COMPUTE:               // nothing to do
       break;
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+    case COMPUTE_CANCELED:               // nothing to do
+      break;
+#endif
     case CLEAN:
       CleanDependants();
       RemoveSubMeshElementsAndNodes();
@@ -1370,6 +1374,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           algo->InitComputeError();
           MemoryReserve aMemoryReserve;
           SMDS_Mesh::CheckMemory();
+          Kernel_Utils::Localizer loc;
           if ( !_father->HasShapeToMesh() ) // no shape
           {
             SMESH_MesherHelper helper( *_father );
@@ -1427,18 +1432,29 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             ret = false;
         }
-        if (ret && !_alwaysComputed && shape == _subShape) { // check if anything was built
-          ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
+        TopExp_Explorer subS(shape, _subShape.ShapeType());
+        if (ret) // check if anything was built
+        {
+          for (; ret && subS.More(); subS.Next())
+            ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed();
         }
         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;
+          for (subS.ReInit(); subS.More(); subS.Next())
+          {
+            SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+            if ( !sm->IsMeshComputed() )
+            {
+              if ( !sm->_computeError )
+                sm->_computeError = SMESH_ComputeError::New();
+              if ( sm->_computeError->IsOK() )
+                sm->_computeError->myName = COMPERR_ALGO_FAILED;
+              sm->_computeState = FAILED_TO_COMPUTE;
+              sm->_computeError->myAlgo = algo;
+            }
+          }
         }
         if (ret)
         {
@@ -1447,6 +1463,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
       }
       break;
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+    case COMPUTE_CANCELED:               // nothing to do
+      break;
+#endif
     case CLEAN:
       CleanDependants();
       RemoveSubMeshElementsAndNodes();
@@ -1496,6 +1516,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       break;
     case COMPUTE:               // nothing to do
       break;
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+    case COMPUTE_CANCELED:               // nothing to do
+      break;
+#endif
     case CLEAN:
       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
       RemoveSubMeshElementsAndNodes();
@@ -1517,11 +1541,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
       break;
     case CHECK_COMPUTE_STATE:
-      if ( !IsMeshComputed() )
+      if ( !IsMeshComputed() ) {
         if (_algoState == HYP_OK)
           _computeState = READY_TO_COMPUTE;
         else
           _computeState = NOT_READY;
+      }
       break;
     default:
       ASSERT(0);
@@ -1535,6 +1560,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     switch (event)
     {
     case MODIF_ALGO_STATE:
+      if ( !IsEmpty() )
+        ComputeStateEngine( CLEAN );
       algo = gen->GetAlgo((*_father), _subShape);
       if (algo && !algo->NeedDescretBoundary())
         CleanDependsOn(); // clean sub-meshes with event CLEAN
@@ -1545,6 +1572,14 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       break;
     case COMPUTE:      // nothing to do
       break;
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+    case COMPUTE_CANCELED:
+      {
+        algo = gen->GetAlgo((*_father), _subShape);
+        algo->CancelCompute();
+      }
+      break;
+#endif
     case CLEAN:
       CleanDependants(); // submeshes dependent on me should be cleaned as well
       RemoveSubMeshElementsAndNodes();
@@ -1685,7 +1720,7 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
     // Check my state
     if ( !_computeError || _computeError->IsOK() )
     {
-      _computeState = COMPUTE_OK;
+      _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE;
     }
     else
     {
@@ -1702,20 +1737,8 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
       if ( _computeError->myComment.size() > 0 )
         text << " \"" << _computeError->myComment << "\"";
 
-#ifdef _DEBUG_
-      MESSAGE_BEGIN ( text );
-      // Show vertices location of a failed shape
-      TopTools_IndexedMapOfShape vMap;
-      TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
-      MESSAGE_ADD ( "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") );
-      for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
-        gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
-        MESSAGE_ADD ( "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " "
-                   << P.X() << " " << P.Y() << " " << P.Z() << " " );
-      }
-#else
       INFOS( text );
-#endif
+
       _computeState = FAILED_TO_COMPUTE;
       noErrors = false;
     }
@@ -2053,8 +2076,6 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener)
  * \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
  */
 //================================================================================
@@ -2065,7 +2086,11 @@ void SMESH_subMesh::NotifyListenersOnEvent( const int         event,
 {
   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 );
+    if ( (*l_d).first->myBusySM.insert( this ).second )
+    {
+      l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
+      l_d->first->myBusySM.erase( this );
+    }
 }
 
 //================================================================================