Salome HOME
Merge from V5_1_4_BR 07/05/2010
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index bbb5fa96a45e3c7f8c7e2da6dcaf1b826d6c1252..4d92816fc560af3ed3ed77e3a0c3cc519fdb7163 100644 (file)
@@ -1,6 +1,6 @@
-//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  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
 //
 //  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
-//  $Header$
-
+//
 #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 "utilities.h"
 #include "OpUtil.hxx"
+#include "Basics_Utils.hxx"
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
@@ -55,6 +56,8 @@
 #include <Standard_OutOfMemory.hxx>
 #include <Standard_ErrorHandler.hxx>
 
+#include <numeric>
+
 using namespace std;
 
 //=============================================================================
@@ -83,22 +86,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;
-       }
+        }
 }
 
 //=============================================================================
@@ -186,6 +189,19 @@ void SMESH_subMesh::SetIsAlwaysComputed(bool isAlCo)
     ComputeStateEngine( CHECK_COMPUTE_STATE );
 }
 
+//=======================================================================
+/*!
+ * \brief Return true if no mesh entities is bound to the submesh
+ */
+//=======================================================================
+
+bool SMESH_subMesh::IsEmpty() const
+{
+  if (SMESHDS_SubMesh * subMeshDS = ((SMESH_subMesh*)this)->GetSubMeshDS())
+    return (!subMeshDS->NbElements() && !subMeshDS->NbNodes());
+  return true;
+}
+
 //=======================================================================
 //function : IsMeshComputed
 //purpose  : check if _subMeshDS contains mesh elements
@@ -380,7 +396,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
     }
   case TopAbs_COMPSOLID:
     {
-               //MESSAGE("compsolid");
+                //MESSAGE("compsolid");
       for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
            exp.Next())
       {
@@ -436,7 +452,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
       for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More();
            exp.Next())
       {
-                       InsertDependence(exp.Current());
+                        InsertDependence(exp.Current());
                       }
       break;
     }
@@ -483,8 +499,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;
 }
 
 
@@ -497,16 +513,15 @@ const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
 bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
 {
   int aHypDim   = theHypothesis->GetDim();
-  if(_father->HasShapeToMesh()) {
-    int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
-    if ( aHypDim <= aShapeDim )
-      return true;
+  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;
   }
-  else
-    //Only 3D hypothesis may be assigned to the mesh w/o geometry
-    return aHypDim == 3;
-//   if ( aHypDim < aShapeDim )
-//     return ( _father->IsMainShape( _subShape ));
+  if ( aHypDim <= aShapeDim )
+    return true;
 
   return false;
 }
@@ -598,6 +613,7 @@ SMESH_Hypothesis::Hypothesis_Status
 
   int oldAlgoState = _algoState;
   bool modifiedHyp = (event == MODIF_HYP);  // if set to true, force event MODIF_ALGO_STATE
+  bool needFullClean = false;
 
   bool isApplicableHyp = IsApplicableHypotesis( anHyp );
 
@@ -607,14 +623,22 @@ SMESH_Hypothesis::Hypothesis_Status
     // check if a shape needed by algo is present
     // -------------------------------------------
     algo = static_cast< SMESH_Algo* >( anHyp );
-    if(_father->GetShapeToMesh() != SMESH_Mesh::PseudoShape())
-      if ( !_father->HasShapeToMesh() && algo->NeedShape() )
-        return SMESH_Hypothesis::HYP_BAD_GEOMETRY;
+    if ( !_father->HasShapeToMesh() && algo->NeedShape() )
+      return SMESH_Hypothesis::HYP_NEED_SHAPE;
     // ----------------------
     // check mesh conformity
     // ----------------------
     if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
       return SMESH_Hypothesis::HYP_NOTCONFORM;
+
+    // check if all-dimensional algo is hidden by other local one
+    if ( event == ADD_ALGO ) {
+      SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
+      filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
+      filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
+      if ( SMESH_Algo * curAlgo = (SMESH_Algo*) _father->GetHypothesis( _subShape, filter, true ))
+        needFullClean = ( !curAlgo->NeedDescretBoundary() );
+    }
   }
 
   // ----------------------------------
@@ -625,17 +649,6 @@ SMESH_Hypothesis::Hypothesis_Status
     if ( ! CanAddHypothesis( anHyp )) // check dimension
       return SMESH_Hypothesis::HYP_BAD_DIM;
 
-    if(anHyp->GetDim() == 3 && !_father->HasShapeToMesh()
-       && event == ADD_ALGO) {
-      //Only NETGEN_3D and GHS3D_3D can be assigned to the Mesh w/o geometryy
-      bool isNetgen3D = (strcmp( "NETGEN_3D", anHyp->GetName()) == 0);
-      bool  isGhs3d = (strcmp( "GHS3D_3D", anHyp->GetName()) == 0);
-      if( !isNetgen3D && !isGhs3d)
-        return SMESH_Hypothesis::HYP_BAD_DIM;
-    }
-      
-
-    
     if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
 
@@ -659,10 +672,7 @@ SMESH_Hypothesis::Hypothesis_Status
         // clean all mesh in the tree of the current submesh;
         // we must perform it now because later
         // we will have no information about the type of the removed algo
-        CleanDependants();
-       ComputeStateEngine( CLEAN );
-        CleanDependsOn();
-        ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+        needFullClean = true;
       }
     }
   }
@@ -941,6 +951,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
       {
@@ -982,11 +998,13 @@ SMESH_Hypothesis::Hypothesis_Status
     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
     for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
       if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
-        if ( !upperAlgo->NeedDescretBoundary() )
+        if ( !upperAlgo->NeedDescretBoundary() && !upperAlgo->SupportSubmeshes())
           ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
     }
     // is algo hiding?
-    if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) {
+    if ( ret == SMESH_Hypothesis::HYP_OK &&
+         !algo->NeedDescretBoundary()    &&
+         !algo->SupportSubmeshes()) {
       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 ))
@@ -1011,6 +1029,13 @@ SMESH_Hypothesis::Hypothesis_Status
     }
   }
 
+  if ( needFullClean ) {
+    // added or removed algo is all-dimensional
+    ComputeStateEngine( CLEAN );
+    CleanDependsOn();
+    ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+  }
+
   if (stateChange || modifiedHyp)
     ComputeStateEngine(MODIF_ALGO_STATE);
 
@@ -1127,48 +1152,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;
+        }
 }
 
 //================================================================================
@@ -1195,7 +1220,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);
@@ -1223,7 +1248,12 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     _computeState = READY_TO_COMPUTE;
     SMESHDS_SubMesh* smDS = GetSubMeshDS();
     if ( smDS && smDS->NbNodes() ) {
-      _computeState = COMPUTE_OK;
+      if ( event == CLEAN ) {
+        CleanDependants();
+        cleanSubMesh( this );
+      }
+      else
+        _computeState = COMPUTE_OK;
     }
     else if ( event == COMPUTE && !_alwaysComputed ) {
       const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
@@ -1258,13 +1288,13 @@ 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;
     case CLEAN:
       CleanDependants();
       RemoveSubMeshElementsAndNodes();
       break;
-    case SUBMESH_COMPUTED:     // nothing to do
+    case SUBMESH_COMPUTED:      // nothing to do
       break;
     case SUBMESH_RESTORED:
       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
@@ -1309,10 +1339,16 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           SetAlgoState(MISSING_HYP);
           break;
         }
+        TopoDS_Shape shape = _subShape;
         // check submeshes needed
         if (_father->HasShapeToMesh() ) {
-          bool subComputed = SubMeshesComputed();
+          bool subComputed = false;
+          if (!algo->OnlyUnaryInput())
+            shape = GetCollection( gen, algo, subComputed );
+          else
+            subComputed = SubMeshesComputed();
           ret = ( algo->NeedDescretBoundary() ? subComputed :
+                  algo->SupportSubmeshes() ? true :
                   ( !subComputed || _father->IsNotConformAllowed() ));
           if (!ret) {
             _computeState = FAILED_TO_COMPUTE;
@@ -1329,7 +1365,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         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;
@@ -1337,6 +1372,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 );
@@ -1346,16 +1382,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           }
           else
           {
-            if (!algo->OnlyUnaryInput()) {
-              shape = GetCollection( gen, algo );
-            }
             ret = algo->Compute((*_father), shape);
           }
-          if ( !ret )
+          if ( !_computeError || ( !ret && _computeError->IsOK() ) ) // algo can set _computeError of submesh
             _computeError = algo->GetComputeError();
         }
         catch ( std::bad_alloc& exc ) {
-          printf("std::bad_alloc thrown inside algo->Compute()\n");
+          MESSAGE("std::bad_alloc thrown inside algo->Compute()");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
             //_computeError->myComment = exc.what();
@@ -1364,7 +1397,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           throw exc;
         }
         catch ( Standard_OutOfMemory& exc ) {
-          printf("Standard_OutOfMemory thrown inside algo->Compute()\n");
+          MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
             //_computeError->myComment = exc.what();
@@ -1397,7 +1430,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             ret = false;
         }
-        if (ret && !_alwaysComputed) { // check if anything was built
+        if (ret && !_alwaysComputed && shape == _subShape) { // check if anything was built
           ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
         }
         bool isComputeErrorSet = !CheckComputeError( algo, shape );
@@ -1505,6 +1538,9 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     switch (event)
     {
     case MODIF_ALGO_STATE:
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo && !algo->NeedDescretBoundary())
+        CleanDependsOn(); // clean sub-meshes with event CLEAN
       if (_algoState == HYP_OK)
         _computeState = READY_TO_COMPUTE;
       else
@@ -1553,6 +1589,63 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
   return ret;
 }
 
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
+{
+  _computeError.reset();
+
+  bool ret = true;
+
+  if (_subShape.ShapeType() == TopAbs_VERTEX) {
+    vector<int> aVec(SMDSEntity_Last,0);
+    aVec[SMDSEntity_Node] = 1;
+    aResMap.insert(make_pair(this,aVec));
+    return ret;
+  }
+
+  SMESH_Gen *gen = _father->GetGen();
+  SMESH_Algo *algo = 0;
+  SMESH_Hypothesis::Hypothesis_Status hyp_status;
+
+  algo = gen->GetAlgo((*_father), _subShape);
+  if(algo && !aResMap.count(this) )
+  {
+    ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+    if (!ret) return false;
+
+    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);
+
+    aResMap.insert( make_pair( this,vector<int>(0)));
+  }
+
+  return ret;
+}
+
+
 //=======================================================================
 /*!
  * \brief Update compute_state by _computeError and send proper events to
@@ -1584,7 +1677,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 ))
+          if ( !sm->CheckComputeError( theAlgo, sm->GetSubShape() ))
             noErrors = false;
           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
         }
@@ -1613,15 +1706,15 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t
         text << " \"" << _computeError->myComment << "\"";
 
 #ifdef _DEBUG_
-      cout << text << endl;
+      MESSAGE_BEGIN ( text );
       // 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;
+      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 ) )));
-        cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
-        cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
+        MESSAGE_ADD ( "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " "
+                   << P.X() << " " << P.Y() << " " << P.Z() << " " );
       }
 #else
       INFOS( text );
@@ -1777,10 +1870,14 @@ void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
 //           meshed at once along with _subShape
 //=======================================================================
 
-TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
+TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen,
+                                          SMESH_Algo* theAlgo,
+                                          bool &      theSubComputed)
 {
   MESSAGE("SMESH_subMesh::GetCollection");
 
+  theSubComputed = SubMeshesComputed();
+
   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
 
   if ( mainShape.IsSame( _subShape ))
@@ -1809,9 +1906,11 @@ TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlg
     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
     {
       SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
-      if (anAlgo == theAlgo &&
-          anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
+      if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
+          anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
         aBuilder.Add( aCompound, S );
+      if ( !subMesh->SubMeshesComputed() )
+        theSubComputed = false;
     }
   }
 
@@ -2060,7 +2159,8 @@ namespace {
               SMESH_subMesh*                 prepend,
               SMESH_subMesh*                 append): myIt(subIt),myAppend(append)
     {
-      myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0;
+      myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
+      if ( myCur == append ) append = 0;
     }
     /// Return true if and only if there are other object in this iterator
     virtual bool more()
@@ -2111,3 +2211,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();
+}