]> SALOME platform Git repositories - modules/smesh.git/blobdiff - src/SMESH/SMESH_subMesh.cxx
Salome HOME
Merge from V6_3_BR branch (Windows porting) 27/10/2011
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index efd05b9c1c94bd64d7eb07f3dc25736a56db8f8a..fb86778c7b8105c7f081ebe913a845bc2bd48939 100644 (file)
@@ -1,29 +1,29 @@
-//  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
-//
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// 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
+
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_subMesh.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//
+
 #include "SMESH_subMesh.hxx"
 
 #include "SMESH_Algo.hxx"
 #include "SMESH_subMeshEventListener.hxx"
 #include "SMESH_Comment.hxx"
 #include "SMDS_SetIterator.hxx"
+#include "SMDSAbs_ElementType.hxx"
+
+#include <Basics_OCCTVersion.hxx>
 
 #include "utilities.h"
 #include "OpUtil.hxx"
+#include "Basics_Utils.hxx"
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
@@ -53,6 +57,8 @@
 #include <Standard_OutOfMemory.hxx>
 #include <Standard_ErrorHandler.hxx>
 
+#include <numeric>
+
 using namespace std;
 
 //=============================================================================
@@ -81,22 +87,22 @@ SMESH_subMesh::SMESH_subMesh(int                  Id,
                              SMESHDS_Mesh *       meshDS,
                              const TopoDS_Shape & aSubShape)
 {
-       _subShape = aSubShape;
-       _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
-       _father = father;
-       _Id = Id;
-       _dependenceAnalysed = _alwaysComputed = false;
-
-       if (_subShape.ShapeType() == TopAbs_VERTEX)
-       {
-               _algoState = HYP_OK;
-               _computeState = READY_TO_COMPUTE;
-       }
-       else
-       {
+        _subShape = aSubShape;
+        _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
+        _father = father;
+        _Id = Id;
+        _dependenceAnalysed = _alwaysComputed = false;
+
+        if (_subShape.ShapeType() == TopAbs_VERTEX)
+        {
+                _algoState = HYP_OK;
+                _computeState = READY_TO_COMPUTE;
+        }
+        else
+        {
           _algoState = NO_ALGO;
           _computeState = NOT_READY;
-       }
+        }
 }
 
 //=============================================================================
@@ -260,7 +266,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();
@@ -367,23 +373,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());
       }
@@ -391,9 +398,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());
       }
@@ -402,8 +408,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());
       }
@@ -412,8 +417,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());
       }
@@ -423,8 +427,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());
         }
@@ -434,8 +437,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());
       }
@@ -444,11 +446,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:
@@ -494,8 +495,8 @@ void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
 
 const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
 {
-       //MESSAGE("SMESH_subMesh::GetSubShape");
-       return _subShape;
+        //MESSAGE("SMESH_subMesh::GetSubShape");
+        return _subShape;
 }
 
 
@@ -509,12 +510,13 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons
 {
   int aHypDim   = theHypothesis->GetDim();
   int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
-  if (aHypDim == 3 && aShapeDim == 3) {
-    // check case of open shell
-    //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed())
-    if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape))
-      return false;
-  }
+  // issue 21106. Forbid 3D mesh on the SHELL
+  // if (aHypDim == 3 && aShapeDim == 3) {
+  //   // check case of open shell
+  //   //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed())
+  //   if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape))
+  //     return false;
+  // }
   if ( aHypDim <= aShapeDim )
     return true;
 
@@ -530,8 +532,14 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
                                           const TopAbs_ShapeEnum  theShapeType)
 {
   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
+  {
     // algorithm
-    return ( theHypothesis->GetShapeType() & (1<< theShapeType));
+    if ( theHypothesis->GetShapeType() & (1<< theShapeType))
+      // issue 21106. Forbid 3D mesh on the SHELL
+      return !( theHypothesis->GetDim() == 3 && theShapeType == TopAbs_SHELL );
+    else
+      return false;
+  }
 
   // hypothesis
   switch ( theShapeType ) {
@@ -946,6 +954,12 @@ SMESH_Hypothesis::Hypothesis_Status
       break;
     }
     case REMOVE_FATHER_ALGO: {
+      // IPAL21346. Edges not removed when Netgen 1d-2d is removed from a SOLID.
+      // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID.
+      algo = dynamic_cast<SMESH_Algo*> (anHyp);
+      if (!algo->NeedDescretBoundary())
+        needFullClean = true;
+
       algo = gen->GetAlgo((*_father), _subShape);
       if (algo == NULL)  // no more applying algo on father
       {
@@ -994,9 +1008,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;
     }
   }
@@ -1141,48 +1158,48 @@ void SMESH_subMesh::CleanDependsOn()
 
 void SMESH_subMesh::DumpAlgoState(bool isMain)
 {
-       int dim = SMESH_Gen::GetShapeDim(_subShape);
+        int dim = SMESH_Gen::GetShapeDim(_subShape);
 //   if (dim < 1) return;
-       if (isMain)
-       {
-               const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
-               map < int, SMESH_subMesh * >::const_iterator itsub;
-               for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-               {
-                       SMESH_subMesh *sm = (*itsub).second;
-                       sm->DumpAlgoState(false);
-               }
-       }
-       int type = _subShape.ShapeType();
-       MESSAGE("dim = " << dim << " type of shape " << type);
-       switch (_algoState)
-       {
-       case NO_ALGO:
-               MESSAGE(" AlgoState = NO_ALGO");
-               break;
-       case MISSING_HYP:
-               MESSAGE(" AlgoState = MISSING_HYP");
-               break;
-       case HYP_OK:
-               MESSAGE(" AlgoState = HYP_OK");
-               break;
-       }
-       switch (_computeState)
-       {
-       case NOT_READY:
-               MESSAGE(" ComputeState = NOT_READY");
-               break;
-       case READY_TO_COMPUTE:
-               MESSAGE(" ComputeState = READY_TO_COMPUTE");
-               break;
-       case COMPUTE_OK:
-               MESSAGE(" ComputeState = COMPUTE_OK");
-               break;
-       case FAILED_TO_COMPUTE:
-               MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
-               break;
-       }
+        if (isMain)
+        {
+                const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+
+                map < int, SMESH_subMesh * >::const_iterator itsub;
+                for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+                {
+                        SMESH_subMesh *sm = (*itsub).second;
+                        sm->DumpAlgoState(false);
+                }
+        }
+        int type = _subShape.ShapeType();
+        MESSAGE("dim = " << dim << " type of shape " << type);
+        switch (_algoState)
+        {
+        case NO_ALGO:
+                MESSAGE(" AlgoState = NO_ALGO");
+                break;
+        case MISSING_HYP:
+                MESSAGE(" AlgoState = MISSING_HYP");
+                break;
+        case HYP_OK:
+                MESSAGE(" AlgoState = HYP_OK");
+                break;
+        }
+        switch (_computeState)
+        {
+        case NOT_READY:
+                MESSAGE(" ComputeState = NOT_READY");
+                break;
+        case READY_TO_COMPUTE:
+                MESSAGE(" ComputeState = READY_TO_COMPUTE");
+                break;
+        case COMPUTE_OK:
+                MESSAGE(" ComputeState = COMPUTE_OK");
+                break;
+        case FAILED_TO_COMPUTE:
+                MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
+                break;
+        }
 }
 
 //================================================================================
@@ -1277,13 +1294,17 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       if ( _algoState == HYP_OK )
         _computeState = READY_TO_COMPUTE;
       break;
-    case COMPUTE:              // nothing to do
+    case COMPUTE:               // nothing to do
+      break;
+#ifdef WITH_SMESH_CANCEL_COMPUTE
+    case COMPUTE_CANCELED:               // nothing to do
       break;
+#endif
     case CLEAN:
       CleanDependants();
       RemoveSubMeshElementsAndNodes();
       break;
-    case SUBMESH_COMPUTED:     // nothing to do
+    case SUBMESH_COMPUTED:      // nothing to do
       break;
     case SUBMESH_RESTORED:
       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
@@ -1355,12 +1376,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         _computeState = FAILED_TO_COMPUTE;
         _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
         try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+#if OCC_VERSION_LARGE > 0x06010000
           OCC_CATCH_SIGNALS;
 #endif
           algo->InitComputeError();
           MemoryReserve aMemoryReserve;
           SMDS_Mesh::CheckMemory();
+          Kernel_Utils::Localizer loc;
           if ( !_father->HasShapeToMesh() ) // no shape
           {
             SMESH_MesherHelper helper( *_father );
@@ -1418,26 +1440,41 @@ 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)
+        if (ret && _computeError && _computeError->myName != COMPERR_WARNING )
         {
           _computeError.reset();
         }
         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();
@@ -1487,6 +1524,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();
@@ -1508,11 +1549,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);
@@ -1526,6 +1568,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
@@ -1536,6 +1580,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();
@@ -1591,10 +1643,9 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
   bool ret = true;
 
   if (_subShape.ShapeType() == TopAbs_VERTEX) {
-    std::vector<int> aVec(17);
-    aVec[0] = 1;
-    for(int i=1; i<17; i++) aVec[i] = 0;
-    aResMap.insert(std::make_pair(this,aVec));
+    vector<int> aVec(SMDSEntity_Last,0);
+    aVec[SMDSEntity_Node] = 1;
+    aResMap.insert(make_pair(this,aVec));
     return ret;
   }
 
@@ -1603,15 +1654,32 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
   SMESH_Hypothesis::Hypothesis_Status hyp_status;
 
   algo = gen->GetAlgo((*_father), _subShape);
-  if(algo) {
+  if(algo && !aResMap.count(this) )
+  {
     ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
     if (!ret) return false;
 
-    TopoDS_Shape shape = _subShape;
-
+    if (_father->HasShapeToMesh() && algo->NeedDescretBoundary())
+    {
+      // check submeshes needed
+      bool subMeshEvaluated = true;
+      int dimToCheck = SMESH_Gen::GetShapeDim( _subShape ) - 1;
+      SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,/*complexShapeFirst=*/true);
+      while ( smIt->more() && subMeshEvaluated )
+      {
+        SMESH_subMesh* sm = smIt->next();
+        int dim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
+        if (dim < dimToCheck) break; // the rest subMeshes are all of less dimension
+        const vector<int> & nbs = aResMap[ sm ];
+        subMeshEvaluated = (std::accumulate( nbs.begin(), nbs.end(), 0 ) > 0 );
+      }
+      if ( !subMeshEvaluated )
+        return false;
+    }
     _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
+    ret = algo->Evaluate((*_father), _subShape, aResMap);
 
-    ret = algo->Evaluate((*_father), shape, aResMap);
+    aResMap.insert( make_pair( this,vector<int>(0)));
   }
 
   return ret;
@@ -1660,7 +1728,8 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
     // Check my state
     if ( !_computeError || _computeError->IsOK() )
     {
-      _computeState = COMPUTE_OK;
+      // no error description is set to this sub-mesh, check if any mesh is computed
+      _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE;
     }
     else
     {
@@ -1677,67 +1746,16 @@ 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;
-    }
-  }
-  return noErrors;
-}
-
-//=======================================================================
-//function : ApplyToCollection
-//purpose  : Apply theAlgo to all subshapes in theCollection
-//=======================================================================
-
-bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
-                                       const TopoDS_Shape& theCollection)
-{
-  MESSAGE("SMESH_subMesh::ApplyToCollection");
-  ASSERT ( !theAlgo->NeedDescretBoundary() );
-
-  if ( _computeError )
-    _computeError->myName = COMPERR_OK;
 
-  bool ok = theAlgo->Compute( *_father, theCollection );
+      _computeState = _computeError->IsKO() ? FAILED_TO_COMPUTE : COMPUTE_OK;
 
-  // set _computeState of subshapes
-  TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
-  for ( ; anExplorer.More(); anExplorer.Next() )
-  {
-    if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() ))
-    {
-      bool localOK = subMesh->CheckComputeError( theAlgo );
-      if ( !ok && localOK && !subMesh->IsMeshComputed() )
-      {
-        subMesh->_computeError = theAlgo->GetComputeError();
-        if ( subMesh->_computeError->IsOK() )
-          _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED);
-        localOK = CheckComputeError( theAlgo );
-      }
-      if ( localOK )
-        subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
-      subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE );
+      noErrors = false;
     }
   }
-
-  return true;
+  return noErrors;
 }
 
-
 //=======================================================================
 //function : UpdateSubMeshState
 //purpose  :
@@ -1800,7 +1818,8 @@ void SMESH_subMesh::CleanDependants()
       // will erase mesh on other shapes in a compound
       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
-        if (aSubMesh)
+        if (aSubMesh &&
+            !aSubMesh->IsEmpty() ) // prevent infinite CLEAN via event lesteners
           aSubMesh->ComputeStateEngine(CLEAN);
       }
     }
@@ -2028,8 +2047,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
  */
 //================================================================================
@@ -2040,7 +2057,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 );
+    }
 }
 
 //================================================================================
@@ -2183,3 +2204,29 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS
       ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
   }
 }
+
+//================================================================================
+/*!
+ * \brief  Find common submeshes (based on shared subshapes with other
+  * \param theOther submesh to check
+  * \param theSetOfCommon set of common submesh
+ */
+//================================================================================
+
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+                                     std::set<const SMESH_subMesh*>& theSetOfCommon ) const
+{
+  int oldNb = theSetOfCommon.size();
+  // check main submeshes
+  const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
+  if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
+    theSetOfCommon.insert( this );
+  if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
+    theSetOfCommon.insert( theOther );
+  // check common submeshes
+  map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
+  for( ; mapIt != _mapDepend.end(); mapIt++ )
+    if ( theOther->_mapDepend.find((*mapIt).first) != otherEnd )
+      theSetOfCommon.insert( (*mapIt).second );
+  return oldNb < theSetOfCommon.size();
+}