Salome HOME
Minor doc changes
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index 0d4e2d120877f027f7f48970005a25a6a6963d3b..128316dcf55c87817dbf3e556cb61bf02a660d35 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
 
 #include "SMESH_subMesh.hxx"
 
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESH_Comment.hxx"
 #include "SMESH_Gen.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMeshEventListener.hxx"
-#include "SMESH_Comment.hxx"
-#include "SMDS_SetIterator.hxx"
-#include "SMDSAbs_ElementType.hxx"
 
 #include <Basics_OCCTVersion.hxx>
 
@@ -241,7 +241,7 @@ bool SMESH_subMesh::IsMeshComputed() const
 {
   if ( _alwaysComputed )
     return true;
-  // algo may bind a submesh not to _subShape, eg 3D algo
+  // algo may bind a sub-mesh not to _subShape, eg 3D algo
   // sets nodes on SHELL while _subShape may be SOLID
 
   SMESHDS_Mesh* meshDS = _father->GetMeshDS();
@@ -280,7 +280,7 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const
   int dimToCheck = myDim - 1;
   bool subMeshesComputed = true;
   if ( isFailedToCompute ) *isFailedToCompute = false;
-  // check subMeshes with upper dimension => reverse iteration
+  // check sub-meshes with upper dimension => reverse iteration
   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
   while ( smIt->more() )
   {
@@ -291,67 +291,22 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const
 
     // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
     // in checking of existence of edges if the algo needs only faces. Moreover,
-    // degenerated edges may have no submesh, as after computing NETGEN_2D.
+    // degenerated edges may have no sub-mesh, as after computing NETGEN_2D.
     if ( !_algo || _algo->NeedDiscreteBoundary() ) {
       int dim = SMESH_Gen::GetShapeDim( ss );
       if (dim < dimToCheck)
-        break; // the rest subMeshes are all of less dimension
+        break; // the rest sub-meshes are all of less dimension
     }
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
-    bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes()  )));
+    bool computeOk = ((sm->GetComputeState() == COMPUTE_OK ) ||
+                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() )));
     if (!computeOk)
     {
       subMeshesComputed = false;
+
       if ( isFailedToCompute && !(*isFailedToCompute) )
         *isFailedToCompute = ( sm->GetComputeState() == FAILED_TO_COMPUTE );
 
-      // int type = ss.ShapeType();
-
-      // switch (type)
-      // {
-      // case TopAbs_COMPOUND:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a COMPOUND");
-      //     break;
-      //   }
-      // case TopAbs_COMPSOLID:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a COMPSOLID");
-      //     break;
-      //   }
-      // case TopAbs_SHELL:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a SHEL");
-      //     break;
-      //   }
-      // case TopAbs_WIRE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a WIRE");
-      //     break;
-      //   }
-      // case TopAbs_SOLID:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a SOLID");
-      //     break;
-      //   }
-      // case TopAbs_FACE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a FACE");
-      //     break;
-      //   }
-      // case TopAbs_EDGE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a EDGE");
-      //     break;
-      //   }
-      // default:
-      //   {
-      //     MESSAGE("The not computed sub mesh is of unknown type");
-      //     break;
-      //   }
-      // }
-
       if ( !isFailedToCompute )
         break;
     }
@@ -403,146 +358,49 @@ int SMESH_subMesh::computeCost() const
 
 //=============================================================================
 /*!
- *
- */
-//=============================================================================
-
-// bool SMESH_subMesh::SubMeshesReady()
-// {
-//   bool subMeshesReady = true;
-//   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
-//   while ( smIt->more() ) {
-//     SMESH_subMesh *sm = smIt->next();
-//     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-//                       sm->GetComputeState() == READY_TO_COMPUTE);
-//     if (!computeOk)
-//     {
-//       subMeshesReady = false;
-//       SCRUTE(sm->GetId());
-//       break;
-//     }
-//   }
-//   return subMeshesReady;
-// }
-
-//=============================================================================
-/*!
- * Construct dependence on first level subMeshes. complex shapes (compsolid,
- * shell, wire) are not analysed the same way as simple shapes (solid, face,
- * edge).
- * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
- * with possible multiples occurences. Multiples occurences corresponds to
- * internal frontiers within shapes of the collection and must not be keeped.
- * See FinalizeDependence.
+ * Returns all sub-meshes this one depend on
  */
 //=============================================================================
 
 const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
 {
-  if (_dependenceAnalysed)
+  if ( _dependenceAnalysed || !_father->HasShapeToMesh() )
     return _mapDepend;
 
-  //MESSAGE("SMESH_subMesh::DependsOn");
-
   int type = _subShape.ShapeType();
-  //SCRUTE(type);
   switch (type)
   {
   case TopAbs_COMPOUND:
+  {
+    list< TopoDS_Shape > compounds( 1, _subShape );
+    list< TopoDS_Shape >::iterator comp = compounds.begin();
+    for ( ; comp != compounds.end(); ++comp )
     {
-      //MESSAGE("compound");
-      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())
-      {
-        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())
-      {
-        insertDependence(exp.Current());
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX, TopAbs_EDGE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_COMPSOLID:
-    {
-      //MESSAGE("compsolid");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_SHELL:
-    {
-      //MESSAGE("shell");
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_WIRE:
-    {
-      //MESSAGE("wire");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_SOLID:
-    {
-      //MESSAGE("solid");
-      if(_father->HasShapeToMesh()) {
-        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
+      for ( TopoDS_Iterator sub( *comp ); sub.More(); sub.Next() )
+        switch ( sub.Value().ShapeType() )
         {
-          insertDependence(exp.Current());
+        case TopAbs_COMPOUND:  compounds.push_back( sub.Value() ); break;
+        case TopAbs_COMPSOLID: insertDependence( sub.Value(), TopAbs_SOLID ); break;
+        case TopAbs_SOLID:     insertDependence( sub.Value(), TopAbs_SOLID ); break;
+        case TopAbs_SHELL:     insertDependence( sub.Value(), TopAbs_FACE ); break;
+        case TopAbs_FACE:      insertDependence( sub.Value(), TopAbs_FACE ); break;
+        case TopAbs_WIRE:      insertDependence( sub.Value(), TopAbs_EDGE ); break;
+        case TopAbs_EDGE:      insertDependence( sub.Value(), TopAbs_EDGE ); break;
+        case TopAbs_VERTEX:    insertDependence( sub.Value(), TopAbs_VERTEX ); break;
+        default:;
         }
-      }
-      break;
-    }
-  case TopAbs_FACE:
-    {
-      //MESSAGE("face");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_EDGE:
-    {
-      //MESSAGE("edge");
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
-      {
-        insertDependence(exp.Current());
-      }
-      break;
-    }
-  case TopAbs_VERTEX:
-    {
-      break;
-    }
-  default:
-    {
-      break;
     }
   }
+  break;
+  case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break;
+  case TopAbs_SOLID:     insertDependence( _subShape, TopAbs_FACE );
+  { /*internal EDGE*/    insertDependence( _subShape, TopAbs_EDGE, TopAbs_WIRE ); break; }
+  case TopAbs_SHELL:     insertDependence( _subShape, TopAbs_FACE ); break;
+  case TopAbs_FACE:      insertDependence( _subShape, TopAbs_EDGE ); break;
+  case TopAbs_WIRE:      insertDependence( _subShape, TopAbs_EDGE ); break;
+  case TopAbs_EDGE:      insertDependence( _subShape, TopAbs_VERTEX ); break;
+  default:;
+  }
   _dependenceAnalysed = true;
   return _mapDepend;
 }
@@ -553,32 +411,44 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
  */
 //================================================================================
 
-namespace {
-  int dependsOnMapKey( const SMESH_subMesh* sm )
+namespace
+{
+  int dependsOnMapKey( TopAbs_ShapeEnum type, int shapeID )
   {
-    int type = sm->GetSubShape().ShapeType();
-    int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
-    int cle = sm->GetId();
+    int ordType = 9 - int(type);               // 2 = Vertex, 8 = CompSolid
+    int     cle = shapeID;
     cle += 10000000 * ordType;    // sort map by ordType then index
     return cle;
   }
+  int dependsOnMapKey( const SMESH_subMesh* sm )
+  {
+    return dependsOnMapKey( sm->GetSubShape().ShapeType(), sm->GetId() );
+  }
 }
 
 //=============================================================================
 /*!
- * For simple Shapes (solid, face, edge): add subMesh into dependence list.
+ * Add sub-meshes on sub-shapes of a given type into the dependence map.
  */
 //=============================================================================
 
-void SMESH_subMesh::insertDependence(const TopoDS_Shape aSubShape)
+void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape,
+                                     TopAbs_ShapeEnum   aSubType,
+                                     TopAbs_ShapeEnum   avoidType)
 {
-  SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
-  int cle = dependsOnMapKey( aSubMesh );
-  if ( _mapDepend.find( cle ) == _mapDepend.end())
+  TopExp_Explorer sub( aShape, aSubType, avoidType );
+  for ( ; sub.More(); sub.Next() )
   {
-    _mapDepend[cle] = aSubMesh;
-    const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
-    _mapDepend.insert( subMap.begin(), subMap.end() );
+    SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() );
+    if ( aSubMesh->GetId() == 0 )
+      continue;  // not a sub-shape of the shape to mesh
+    int cle = dependsOnMapKey( aSubMesh );
+    if ( _mapDepend.find( cle ) == _mapDepend.end())
+    {
+      _mapDepend[cle] = aSubMesh;
+      const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
+      _mapDepend.insert( subMap.begin(), subMap.end() );
+    }
   }
 }
 
@@ -593,6 +463,17 @@ bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const
   return other ? _mapDepend.count( dependsOnMapKey( other )) : false;
 }
 
+//================================================================================
+/*!
+ * \brief Return \c true if \a this sub-mesh depends on a \a shape
+ */
+//================================================================================
+
+bool SMESH_subMesh::DependsOn( const int shapeID ) const
+{
+  return DependsOn( _father->GetSubMeshContaining( shapeID ));
+}
+
 //=============================================================================
 /*!
  * Return a shape of \a this sub-mesh
@@ -683,13 +564,14 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
 //================================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
+  SMESH_subMesh::AlgoStateEngine(algo_event event, SMESH_Hypothesis * anHyp)
 {
   // **** les retour des evenement shape sont significatifs
   // (add ou remove fait ou non)
   // le retour des evenement father n'indiquent pas que add ou remove fait
 
   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
+  if ( _Id == 0 ) return ret; // not a sub-shape of the shape to mesh
 
   SMESHDS_Mesh* meshDS =_father->GetMeshDS();
   SMESH_Algo*   algo   = 0;
@@ -979,7 +861,7 @@ SMESH_Hypothesis::Hypothesis_Status
         f.AndNot( SMESH_HypoFilter::Is( algo ));
         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( this, f, true );
         if (prevAlgo &&
-            string(algo->GetName()) != string(prevAlgo->GetName()) )
+            string( algo->GetName()) != prevAlgo->GetName())
           modifiedHyp = true;
       }
       else
@@ -1096,8 +978,8 @@ SMESH_Hypothesis::Hypothesis_Status
 
   // detect algorithm hiding
   //
-  if ( ret == SMESH_Hypothesis::HYP_OK &&
-       ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
+  if ( ret == SMESH_Hypothesis::HYP_OK && 
+       ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) && algo && 
        algo->GetName() == anHyp->GetName() )
   {
     // is algo hidden?
@@ -1182,8 +1064,6 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
        !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
     return true;
 
-  SMESH_Gen* gen =_father->GetGen();
-
   // only local algo is to be checked
   //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
   if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
@@ -1242,7 +1122,7 @@ void SMESH_subMesh::setAlgoState(algo_state state)
 //================================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::SubMeshesAlgoStateEngine(int                event,
+  SMESH_subMesh::SubMeshesAlgoStateEngine(algo_event         event,
                                           SMESH_Hypothesis * anHyp,
                                           bool               exitOnFatal)
 {
@@ -1292,8 +1172,6 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
   }
   else if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() )
   {
-    SMESHDS_Mesh* meshDS = _father->GetMeshDS();
-
     // find sub-meshes to keep elements on
     set< SMESH_subMesh* > smToKeep;
     TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE;
@@ -1305,30 +1183,33 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
       if ( !sm->IsEmpty() )
       {
         const bool sameShapeType = ( prevShapeType == sm->GetSubShape().ShapeType() );
-        bool keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
+        bool       keepSubMeshes = ( sameShapeType && toKeepPrevShapeType );
         if ( !sameShapeType )
         {
           // check if the algo allows presence of global algos of dimension the algo
-          // can generate it-self
+          // can generate it-self;
+          // always keep a node on VERTEX, as this node can be shared by segments
+          // lying on EDGEs not shared by the VERTEX of sm, due to MergeNodes (PAL23068)
           int  shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
-          keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim );
+          keepSubMeshes = ( algoRequiringCleaning->NeedLowerHyps( shapeDim ) || shapeDim == 0 );
           prevShapeType = sm->GetSubShape().ShapeType();
           toKeepPrevShapeType = keepSubMeshes;
         }
         if ( !keepSubMeshes )
         {
-          // look for an algo assigned to sm
-          bool algoFound = false;
-          const list<const SMESHDS_Hypothesis*>& hyps = meshDS->GetHypothesis( sm->_subShape );
-          list<const SMESHDS_Hypothesis*>::const_iterator h = hyps.begin();
-          for ( ; ( !algoFound && h != hyps.end() ); ++h )
-            algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
-          keepSubMeshes = algoFound;
+          // look for a local algo used to mesh sm
+          TopoDS_Shape algoShape = SMESH_MesherHelper::GetShapeOfHypothesis
+            ( algoRequiringCleaning, _subShape, _father );
+          SMESH_HypoFilter moreLocalAlgo;
+          moreLocalAlgo.Init( SMESH_HypoFilter::IsMoreLocalThan( algoShape, *_father ));
+          moreLocalAlgo.And ( SMESH_HypoFilter::IsAlgo() );
+          bool localAlgoFound = _father->GetHypothesis( sm->_subShape, moreLocalAlgo, true );
+          keepSubMeshes = localAlgoFound;
         }
         // remember all sub-meshes of sm
         if ( keepSubMeshes )
         {
-          SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false,true);
+          SMESH_subMeshIteratorPtr smIt2 = sm->getDependsOnIterator(true);
           while ( smIt2->more() )
             smToKeep.insert( smIt2->next() );
         }
@@ -1353,48 +1234,32 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
 
 void SMESH_subMesh::DumpAlgoState(bool isMain)
 {
-  // if (dim < 1) return;
-        if (isMain)
-        {
-                const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+  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 = " << SMESH_Gen::GetShapeDim(_subShape) <<
-                " type of shape " << _subShape.ShapeType());
-        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;
-        }
+    map < int, SMESH_subMesh * >::const_iterator itsub;
+    for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+    {
+      SMESH_subMesh *sm = (*itsub).second;
+      sm->DumpAlgoState(false);
+    }
+  }
+  MESSAGE("dim = " << SMESH_Gen::GetShapeDim(_subShape) <<
+          " type of shape " << _subShape.ShapeType());
+  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;
+  }
 }
 
 //================================================================================
@@ -1437,7 +1302,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh )
  */
 //=============================================================================
 
-bool SMESH_subMesh::ComputeStateEngine(int event)
+bool SMESH_subMesh::ComputeStateEngine(compute_event event)
 {
   switch ( event ) {
   case MODIF_ALGO_STATE:
@@ -1714,6 +1579,36 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           _computeError.reset();
         }
 
+        // transform errors into warnings if it is caused by mesh edition (imp 0023068)
+        if (!ret && _father->GetIsModified() )
+        {
+          for (subS.ReInit(); subS.More(); subS.Next())
+          {
+            SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+            if ( !sm->IsMeshComputed() && sm->_computeError )
+            {
+              // check if there is a VERTEX w/o nodes
+              // with READY_TO_COMPUTE state (after MergeNodes())
+              SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+              while ( smIt->more() )
+              {
+                SMESH_subMesh * vertSM = smIt->next();
+                if ( vertSM->_subShape.ShapeType() != TopAbs_VERTEX ) break;
+                if ( vertSM->GetComputeState() == READY_TO_COMPUTE )
+                {
+                  SMESHDS_SubMesh * ds = vertSM->GetSubMeshDS();
+                  if ( !ds || ds->NbNodes() == 0 )
+                  {
+                    sm->_computeState = READY_TO_COMPUTE;
+                    sm->_computeError->myName = COMPERR_WARNING;
+                    break;
+                  }
+                }
+              }
+            }
+          }
+        }
+
         // send event SUBMESH_COMPUTED
         if ( ret ) {
           if ( !algo->NeedDiscreteBoundary() )
@@ -1861,10 +1756,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       removeSubMeshElementsAndNodes();
       break;
     case SUBMESH_COMPUTED:      // allow retry compute
-      if (_algoState == HYP_OK)
-        _computeState = READY_TO_COMPUTE;
-      else
-        _computeState = NOT_READY;
+      if ( IsEmpty() ) // 23061
+      {
+        if (_algoState == HYP_OK)
+          _computeState = READY_TO_COMPUTE;
+        else
+          _computeState = NOT_READY;
+      }
       break;
     case SUBMESH_RESTORED:
       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
@@ -1924,12 +1822,12 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
   SMESH_Hypothesis::Hypothesis_Status hyp_status;
 
   algo = GetAlgo();
-  if(algo && !aResMap.count(this) )
+  if( algo && !aResMap.count( this ))
   {
     ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
     if (!ret) return false;
 
-    if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary())
+    if (_father->HasShapeToMesh() && algo->NeedDiscreteBoundary() )
     {
       // check submeshes needed
       bool subMeshEvaluated = true;
@@ -1947,8 +1845,23 @@ bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
         return false;
     }
     _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
-    ret = algo->Evaluate((*_father), _subShape, aResMap);
 
+    if ( IsMeshComputed() )
+    {
+      vector<int> & nbEntities = aResMap[ this ];
+      nbEntities.resize( SMDSEntity_Last, 0 );
+      if ( SMESHDS_SubMesh* sm = GetSubMeshDS() )
+      {
+        nbEntities[ SMDSEntity_Node ] = sm->NbNodes();
+        SMDS_ElemIteratorPtr   elemIt = sm->GetElements();
+        while ( elemIt->more() )
+          nbEntities[ elemIt->next()->GetEntityType() ]++;
+      }
+    }
+    else
+    {
+      ret = algo->Evaluate((*_father), _subShape, aResMap);
+    }
     aResMap.insert( make_pair( this,vector<int>(0)));
   }
 
@@ -2056,7 +1969,7 @@ void SMESH_subMesh::updateSubMeshState(const compute_state theState)
 //purpose  :
 //=======================================================================
 
-void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf)
+void SMESH_subMesh::ComputeSubMeshStateEngine(compute_event event, const bool includeSelf)
 {
   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false);
   while ( smIt->more() )
@@ -2077,11 +1990,10 @@ void SMESH_subMesh::updateDependantsState(const compute_event theEvent)
   }
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : cleanDependants
+//purpose  : 
+//=======================================================================
 
 void SMESH_subMesh::cleanDependants()
 {
@@ -2102,11 +2014,10 @@ void SMESH_subMesh::cleanDependants()
   }
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
+//=======================================================================
+//function : removeSubMeshElementsAndNodes
+//purpose  : 
+//=======================================================================
 
 void SMESH_subMesh::removeSubMeshElementsAndNodes()
 {
@@ -2168,10 +2079,10 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
     const TopoDS_Shape&  S = subMesh->_subShape;
     if ( S.ShapeType() != this->_subShape.ShapeType() )
       continue;
-    theSubs.push_back( subMesh );
     if ( subMesh == this )
     {
       aBuilder.Add( aCompound, S );
+      theSubs.push_back( subMesh );
     }
     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
     {
@@ -2182,6 +2093,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
         aBuilder.Add( aCompound, S );
         if ( !subMesh->SubMeshesComputed() )
           theSubComputed = false;
+        theSubs.push_back( subMesh );
       }
     }
   }
@@ -2467,9 +2379,8 @@ void SMESH_subMesh::deleteOwnListeners()
   list< OwnListenerData >::iterator d;
   for ( d = _ownListeners.begin(); d != _ownListeners.end(); ++d )
   {
-    if ( !_father->MeshExists( d->myMeshID ))
-      continue;
-    if ( _father->GetId() == d->myMeshID && !_father->GetSubMeshContaining( d->mySubMeshID ))
+    SMESH_Mesh* mesh = _father->FindMesh( d->myMeshID );
+    if ( !mesh || !mesh->GetSubMeshContaining( d->mySubMeshID ))
       continue;
     d->mySubMesh->DeleteEventListener( d->myListener );
   }
@@ -2530,7 +2441,7 @@ void SMESH_subMeshEventListener::ProcessEvent(const int          event,
     switch ( event ) {
     case SMESH_subMesh::CLEAN:
       for ( ; smIt != smEnd; ++ smIt)
-        (*smIt)->ComputeStateEngine( event );
+        (*smIt)->ComputeStateEngine( SMESH_subMesh::compute_event( event ));
       break;
     case SMESH_subMesh::COMPUTE:
     case SMESH_subMesh::COMPUTE_SUBMESH:
@@ -2555,7 +2466,7 @@ namespace {
   {
     _Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
               SMESH_subMesh*                 prepend,
-              SMESH_subMesh*                 append): myIt(subIt),myAppend(append)
+              SMESH_subMesh*                 append): myAppend(append), myIt(subIt)
     {
       myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
       if ( myCur == append ) append = 0;
@@ -2657,16 +2568,18 @@ void SMESH_subMesh::ClearAncestors()
  */
 //================================================================================
 
-bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh*            theOther,
                                      std::set<const SMESH_subMesh*>& theSetOfCommon ) const
 {
-  int oldNb = theSetOfCommon.size();
+  size_t 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++ )