Salome HOME
fix bug PAL10974: check if SubMeshesComputed() by presence of nodes in submesh.
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index 2e6799ed22b80a7348e8c5f73bfc0dde843632ae..777c09103e17d266c643efea950e5b3156e11dfa 100644 (file)
@@ -1,23 +1,23 @@
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //
 //  Copyright (C) 2003  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 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//  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 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
 //
 //
 //
@@ -32,14 +32,26 @@ using namespace std;
 #include "SMESH_Mesh.hxx"
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESH_HypoFilter.hxx"
+
 #include "utilities.h"
 #include "OpUtil.hxx"
 
+#include <BRep_Builder.hxx>
+
 #include <TopExp.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+
+#ifdef _DEBUG_
+#include <gp_Pnt.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#endif
 
 //=============================================================================
 /*!
@@ -50,15 +62,12 @@ using namespace std;
 SMESH_subMesh::SMESH_subMesh(int Id, SMESH_Mesh * father, SMESHDS_Mesh * meshDS,
        const TopoDS_Shape & aSubShape)
 {
-       //MESSAGE("SMESH_subMesh::SMESH_subMesh");
        _subShape = aSubShape;
        _meshDS = meshDS;
        _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
        _father = father;
        _Id = Id;
-       _vertexSet = false;                     // only for Vertex subMesh
        _dependenceAnalysed = false;
-       _dependantsFound = false;
 
        if (_subShape.ShapeType() == TopAbs_VERTEX)
        {
@@ -74,7 +83,7 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_Mesh * father, SMESHDS_Mesh * meshDS,
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
@@ -86,11 +95,11 @@ SMESH_subMesh::~SMESH_subMesh()
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
-int SMESH_subMesh::GetId()
+int SMESH_subMesh::GetId() const
 {
        //MESSAGE("SMESH_subMesh::GetId");
        return _Id;
@@ -98,85 +107,11 @@ int SMESH_subMesh::GetId()
 
 //=============================================================================
 /*!
- * Given a subShape, find the subMesh is associated to this subShape or
- * to a collection of shapes containing this subShape. Collection = compsolid,
- * shell, wire
+ *
  */
 //=============================================================================
 
-// bool SMESH_subMesh::Contains(const TopoDS_Shape & aSubShape)
-//   throw (SALOME_Exception)
-// {
-//   //MESSAGE("SMESH_subMesh::Contains");
-//   bool contains = false;
-//   int type = _subShape.ShapeType();
-//   int typesub = aSubShape.ShapeType();
-//   //SCRUTE(type)
-//   //SCRUTE(typesub)
-//   switch (type)
-//     {
-// //     case TopAbs_COMPOUND:
-// //       {
-// //   //MESSAGE("---");
-// //   throw SALOME_Exception(LOCALIZED("Compound not yet treated"));
-// //   break;
-// //       }
-//     case TopAbs_COMPSOLID:
-//       {
-//  //MESSAGE("---");
-//  for (TopExp_Explorer exp(aSubShape,TopAbs_SOLID);exp.More();exp.Next())
-//    {
-//      contains = _subShape.IsSame(exp.Current());
-//      if (contains) break;
-//    }
-//  break;
-//       }
-//     case TopAbs_SHELL:
-//       {
-//  //MESSAGE("---");
-//  for (TopExp_Explorer exp(aSubShape,TopAbs_FACE);exp.More();exp.Next())
-//    {
-//      contains = _subShape.IsSame(exp.Current());
-//      if (contains) break;
-//    }
-//  break;
-//       }
-//     case TopAbs_WIRE:
-//       {
-//  //MESSAGE("---");
-//  for (TopExp_Explorer exp(aSubShape,TopAbs_EDGE);exp.More();exp.Next())
-//    {
-//      contains = _subShape.IsSame(exp.Current());
-//      if (contains) break;
-//    }
-//  break;
-//       }
-//     case TopAbs_COMPOUND:
-//     case TopAbs_SOLID:
-//     case TopAbs_FACE:
-//     case TopAbs_EDGE:
-//     case TopAbs_VERTEX:
-//       {
-//  //MESSAGE("---");
-//  contains = _subShape.IsSame(aSubShape);
-//  break;
-//       }
-//     default:
-//       {
-//  break;
-//       }
-//     }
-//   //SCRUTE(contains);
-//   return contains;
-// }
-
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
-
-SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() throw(SALOME_Exception)
+SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
 {
        //MESSAGE("SMESH_subMesh::GetSubMeshDS");
        if (_subMeshDS==NULL)
@@ -195,156 +130,169 @@ SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS() throw(SALOME_Exception)
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
-SMESH_subMesh *SMESH_subMesh::GetFirstToCompute() throw(SALOME_Exception)
+SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
 {
-       //MESSAGE("SMESH_subMesh::GetFirstToCompute");
-       const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-       SMESH_subMesh *firstToCompute = 0;
+  if ( !GetSubMeshDS() )
+    _meshDS->NewSubMesh( _meshDS->ShapeToIndex( _subShape ) );
 
-       map < int, SMESH_subMesh * >::const_iterator itsub;
-       for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-       {
-               SMESH_subMesh *sm = (*itsub).second;
-//       SCRUTE(sm->GetId());
-//       SCRUTE(sm->GetComputeState());
-               bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
-               if (readyToCompute)
-               {
-                       firstToCompute = sm;
-                       //SCRUTE(sm->GetId());
-                       break;
-               }
-       }
-       if (firstToCompute)
-       {
-               //MESSAGE("--- submesh to compute");
-               return firstToCompute;  // a subMesh of this
-       }
-       if (_computeState == READY_TO_COMPUTE)
-       {
-               //MESSAGE("--- this to compute");
-               return this;                    // this
-       }
-       //MESSAGE("--- nothing to compute");
-       return 0;                                       // nothing to compute
+  return GetSubMeshDS();
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
-bool SMESH_subMesh::SubMeshesComputed() throw(SALOME_Exception)
+SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
 {
-       //MESSAGE("SMESH_subMesh::SubMeshesComputed");
-       const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+  //MESSAGE("SMESH_subMesh::GetFirstToCompute");
+  const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+  SMESH_subMesh *firstToCompute = 0;
+
+  map < int, SMESH_subMesh * >::const_iterator itsub;
+  for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+  {
+    SMESH_subMesh *sm = (*itsub).second;
+    //       SCRUTE(sm->GetId());
+    //       SCRUTE(sm->GetComputeState());
+    bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
+    if (readyToCompute)
+    {
+      firstToCompute = sm;
+      //SCRUTE(sm->GetId());
+      break;
+    }
+  }
+  if (firstToCompute)
+  {
+    return firstToCompute;     // a subMesh of this
+  }
+  if (_computeState == READY_TO_COMPUTE)
+  {
+    return this;               // this
+  }
+  return 0;                     // nothing to compute
+}
 
-       bool subMeshesComputed = true;
-       map < int, SMESH_subMesh * >::const_iterator itsub;
-       for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-       {
-               SMESH_subMesh *sm = (*itsub).second;
-
-               const TopoDS_Shape & ss = sm->GetSubShape();
-               int type = ss.ShapeType();
-//       SCRUTE(sm->GetId());
-//       SCRUTE(sm->GetComputeState());
-               bool computeOk = (sm->GetComputeState() == COMPUTE_OK);
-               if (!computeOk)
-               {
-                       subMeshesComputed = false;
-
-                       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;
-                           }
-                         }
-
-                       SCRUTE(sm->GetId());
-                       break;
-               }
-       }
-       return subMeshesComputed;
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool SMESH_subMesh::SubMeshesComputed()
+{
+  //MESSAGE("SMESH_subMesh::SubMeshesComputed");
+  const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+
+  bool subMeshesComputed = true;
+  map < int, SMESH_subMesh * >::const_iterator itsub;
+  for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+  {
+    SMESH_subMesh *sm = (*itsub).second;
+    SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
+    // PAL10974.
+    // There are some tricks with compute states, e.g. Penta_3D leaves
+    // one face with READY_TO_COMPUTE state in order to be able to
+    // recompute 3D when a locale triangle hypo changes (see PAL7428).
+    // So we check if mesh is really present
+    //bool computeOk = (sm->GetComputeState() == COMPUTE_OK);
+    bool computeOk = ( ds && ds->GetNodes()->more() );
+    if (!computeOk)
+    {
+      const TopoDS_Shape & ss = sm->GetSubShape();
+      int type = ss.ShapeType();
+
+      subMeshesComputed = false;
+
+      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;
+        }
+      }
+
+      break;
+    }
+  }
+  return subMeshesComputed;
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
 bool SMESH_subMesh::SubMeshesReady()
 {
-       MESSAGE("SMESH_subMesh::SubMeshesReady");
-       const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
-       bool subMeshesReady = true;
-       map < int, SMESH_subMesh * >::const_iterator itsub;
-       for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-       {
-               SMESH_subMesh *sm = (*itsub).second;
-//       SCRUTE(sm->GetId());
-//       SCRUTE(sm->GetComputeState());
-               bool computeOk = ((sm->GetComputeState() == COMPUTE_OK)
-                       || (sm->GetComputeState() == READY_TO_COMPUTE));
-               if (!computeOk)
-               {
-                       subMeshesReady = false;
-                       SCRUTE(sm->GetId());
-                       break;
-               }
-       }
-       return subMeshesReady;
+  MESSAGE("SMESH_subMesh::SubMeshesReady");
+  const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+
+  bool subMeshesReady = true;
+  map < int, SMESH_subMesh * >::const_iterator itsub;
+  for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+  {
+    SMESH_subMesh *sm = (*itsub).second;
+    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, 
+ * Construct dependence on first level subMeshes. complex shapes (compsolid,
  * shell, wire) are not analysed the same way as simple shapes (solid, face,
- * edge). 
+ * 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.
@@ -354,167 +302,111 @@ bool SMESH_subMesh::SubMeshesReady()
 
 const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn()
 {
-       if (_dependenceAnalysed)
-               return _mapDepend;
-
-       //MESSAGE("SMESH_subMesh::DependsOn");
-
-       int type = _subShape.ShapeType();
-       //SCRUTE(type);
-       switch (type)
-       {
-       case TopAbs_COMPOUND:
-       {
-               //MESSAGE("compound");
-               list < TopoDS_Shape > shellInSolid;
-               for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-                       for (TopExp_Explorer
-                               exp2(exp.Current(), TopAbs_SHELL); exp2.More(); exp2.Next())
-                       {
-                               shellInSolid.push_back(exp2.Current());
-                       }
-               }
-               for (TopExp_Explorer exp(_subShape, TopAbs_SHELL); exp.More();
-                       exp.Next())
-               {
-                       list < TopoDS_Shape >::iterator it1;
-                       bool isInSolid = false;
-                       for (it1 = shellInSolid.begin(); it1 != shellInSolid.end(); it1++)
-                       {
-                               TopoDS_Shape aShape = (*it1);
-                               if (aShape.IsSame(exp.Current()))
-                               {
-                                       isInSolid = true;
-                                       break;
-                               }
-                       }
-                       if (!isInSolid)
-                               InsertDependence(exp.Current());        //only shell not in solid
-               }
-               for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-               for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-               break;
-       }
-       case TopAbs_COMPSOLID:
-       {
+  if (_dependenceAnalysed)
+    return _mapDepend;
+
+  //MESSAGE("SMESH_subMesh::DependsOn");
+
+  int type = _subShape.ShapeType();
+  //SCRUTE(type);
+  switch (type)
+  {
+  case TopAbs_COMPOUND:
+    {
+      //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())
+      {
+          InsertDependence(exp.Current());      //only shell not in solid
+      }
+      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());
+      }
+      break;
+    }
+  case TopAbs_COMPSOLID:
+    {
                //MESSAGE("compsolid");
-               for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-//  list<TopoDS_Shape> shapeList;
-//  for (TopExp_Explorer exp(_subShape,TopAbs_SOLID);exp.More();exp.Next())
-//    {
-//      for (TopExp_Explorer 
-//         exp2(exp.Current(),TopAbs_FACE);exp2.More();exp2.Next())
-//        {
-//      shapeList.push_back(exp2.Current()); 
-//        }
-//    }
-//  FinalizeDependence(shapeList);
-               break;
-       }
-       case TopAbs_SHELL:
-       {
-               //MESSAGE("shell");
-               for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-//  list<TopoDS_Shape> shapeList;
-//  for (TopExp_Explorer exp(_subShape,TopAbs_FACE);exp.More();exp.Next())
-//    {
-//      for (TopExp_Explorer 
-//         exp2(exp.Current(),TopAbs_EDGE);exp2.More();exp2.Next())
-//        {
-//      shapeList.push_back(exp2.Current()); 
-//        }
-//    }
-//  FinalizeDependence(shapeList);
-               break;
-       }
-       case TopAbs_WIRE:
-       {
-               //MESSAGE("wire");
-               for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-//  list<TopoDS_Shape> shapeList;
-//  for (TopExp_Explorer exp(_subShape,TopAbs_EDGE);exp.More();exp.Next())
-//    {
-//      for (TopExp_Explorer 
-//         exp2(exp.Current(),TopAbs_VERTEX);exp2.More();exp2.Next())
-//        {
-//      shapeList.push_back(exp2.Current()); 
-//        }
-//    }
-//  FinalizeDependence(shapeList);
-               break;
-       }
-       case TopAbs_SOLID:
-       {
-               //MESSAGE("solid");
-//  for (TopExp_Explorer exp(_subShape,TopAbs_SHELL);exp.More();exp.Next())
-//    {
-//      InsertDependence(exp.Current());
-//    }
-               for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-                       exp.Next())
-               {
-                       InsertDependence(exp.Current());
-               }
-               break;
-       }
-       case TopAbs_FACE:
-       {
-               //MESSAGE("face");
-//  for (TopExp_Explorer exp(_subShape,TopAbs_WIRE);exp.More();exp.Next())
-//    {
-//      InsertDependence(exp.Current());
-//    }
-               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())
-               {
+      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");
+      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
+           exp.Next())
+      {
+        InsertDependence(exp.Current());
+      }
+      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;
-       }
-       }
-       _dependenceAnalysed = true;
-       return _mapDepend;
+                      }
+      break;
+    }
+  case TopAbs_VERTEX:
+    {
+      break;
+    }
+  default:
+    {
+      break;
+    }
+  }
+  _dependenceAnalysed = true;
+  return _mapDepend;
 }
 
 //=============================================================================
@@ -525,60 +417,31 @@ const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn()
 
 void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
 {
-       //MESSAGE("SMESH_subMesh::InsertDependence");
-       //SMESH_subMesh* aSubMesh = _father->GetSubMeshContaining(aSubShape);
-       //SCRUTE(aSubMesh);
-       //if (! aSubMesh) aSubMesh = _father->GetSubMesh(aSubShape);
-
-       SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
-       int type = aSubShape.ShapeType();
-       int ordType = 9 - type;         // 2 = Vertex, 8 = CompSolid
-       int cle = aSubMesh->GetId();
-       cle += 10000000 * ordType;      // sort map by ordType then index
-       if (_mapDepend.find(cle) == _mapDepend.end())
-       {
-               _mapDepend[cle] = aSubMesh;
-               const map < int, SMESH_subMesh * >&subMap = aSubMesh->DependsOn();
-               map < int, SMESH_subMesh * >::const_iterator im;
-               for (im = subMap.begin(); im != subMap.end(); im++)
-               {
-                       int clesub = (*im).first;
-                       SMESH_subMesh *sm = (*im).second;
-                       if (_mapDepend.find(clesub) == _mapDepend.end())
-                               _mapDepend[clesub] = sm;
-               }
-       }
+  //MESSAGE("SMESH_subMesh::InsertDependence");
+  SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
+  int type = aSubShape.ShapeType();
+  int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
+  int cle = aSubMesh->GetId();
+  cle += 10000000 * ordType;    // sort map by ordType then index
+  if (_mapDepend.find(cle) == _mapDepend.end())
+  {
+    _mapDepend[cle] = aSubMesh;
+    const map < int, SMESH_subMesh * >&subMap = aSubMesh->DependsOn();
+    map < int, SMESH_subMesh * >::const_iterator im;
+    for (im = subMap.begin(); im != subMap.end(); im++)
+    {
+      int clesub = (*im).first;
+      SMESH_subMesh *sm = (*im).second;
+      if (_mapDepend.find(clesub) == _mapDepend.end())
+        _mapDepend[clesub] = sm;
+    }
+  }
 
 }
 
 //=============================================================================
 /*!
- * For collection shapes (compsolid, shell, wire).
- * Add only subMesh figuring only once in multiset to dependence list 
- */
-//=============================================================================
-
-// void SMESH_subMesh::FinalizeDependence(list<TopoDS_Shape>& shapeList)
-// {
-//   //MESSAGE("SMESH_subMesh::FinalizeDependence");
-//   list<TopoDS_Shape>::iterator it1, it2;
-//   for(it1 = shapeList.begin(); it1 != shapeList.end(); it1++)
-//     {
-//       TopoDS_Shape aSubShape = (*it1);
-//       int count = 0;
-//       for(it2 = shapeList.begin(); it2 != shapeList.end(); it2++)
-//  {
-//    TopoDS_Shape other = (*it2);
-//    if (other.IsSame(aSubShape)) count++;
-//  }
-//       if (count == 1) InsertDependence(aSubShape);
-//       SCRUTE(count);
-//     }
-// }
-
-//=============================================================================
-/*!
- * 
+ *
  */
 //=============================================================================
 
@@ -588,462 +451,615 @@ const TopoDS_Shape & SMESH_subMesh::GetSubShape()
        return _subShape;
 }
 
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
-
-bool SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
-throw(SALOME_Exception)
-{
-       //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
-       //SCRUTE(_algoState);
-       //SCRUTE(event);
-
-       // **** 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
-       int dim = SMESH_Gen::GetShapeDim(_subShape);
-
-       if (dim < 1)
-       {
-               _algoState = HYP_OK;
-               //SCRUTE(_algoState);
-               return true;
-       }
-
-       SMESH_Gen *gen = _father->GetGen();
-       bool ret;
-       _oldAlgoState = _algoState;
-       bool modifiedHyp = false;       // if set to true, force event MODIF_ALGO_STATE
-       // in ComputeStateEngine
 
-       switch (_algoState)
-       {
+//=======================================================================
+//function : CanAddHypothesis
+//purpose  : return true if theHypothesis can be attached to me:
+//           its dimention is checked
+//=======================================================================
 
-               // ----------------------------------------------------------------------
+bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
+{
+  int aHypDim   = theHypothesis->GetDim();
+  int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
+  if ( aHypDim <= aShapeDim )
+    return true;
+//   if ( aHypDim < aShapeDim )
+//     return ( _father->IsMainShape( _subShape ));
+
+  return false;
+}
 
-       case NO_ALGO:
-               switch (event)
-               {
-               case ADD_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->AddHypothesis(_subShape, anHyp);
-                       break;
-               case ADD_ALGO:
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
-                       {
-                               ret = _meshDS->AddHypothesis(_subShape, anHyp);
-//        if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
-//        if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
-                               if (ret &&
-                                       (anHyp->GetShapeType() & (1 << _subShape.ShapeType())))
-                               {
-                                       SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                                       ASSERT(algo);
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               case REMOVE_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                       break;
-               case REMOVE_ALGO:
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                       break;
-               case ADD_FATHER_HYP:    // nothing to do
-                       break;
-               case ADD_FATHER_ALGO:   // Algo just added in father
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-//    if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
-//    if (anHyp->GetShapeType() == _subShape.ShapeType())
-                       if (anHyp->GetShapeType() & (1 << _subShape.ShapeType()))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                       }
-                       break;
-               case REMOVE_FATHER_HYP: // nothing to do
-                       break;
-               case REMOVE_FATHER_ALGO:        // nothing to do
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
+//=======================================================================
+//function : IsApplicableHypotesis
+//purpose  : 
+//=======================================================================
 
-               // ----------------------------------------------------------------------
+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));
+
+  // hypothesis
+  int aShapeDim = 100;
+  switch ( theShapeType ) {
+  case TopAbs_EDGE: aShapeDim = 1; break;
+  case TopAbs_FACE: aShapeDim = 2; break;
+  case TopAbs_SHELL:aShapeDim = 3; break;
+  case TopAbs_SOLID:aShapeDim = 3; break;
+//   case TopAbs_VERTEX:
+//   case TopAbs_WIRE:
+//   case TopAbs_COMPSOLID:
+//   case TopAbs_COMPOUND:
+  default:  return false;
+  }
+
+  return ( theHypothesis->GetDim() == aShapeDim );
+}
 
-       case MISSING_HYP:
-               switch (event)
-               {
-               case ADD_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->AddHypothesis(_subShape, anHyp);
-                       if (ret)
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                       }
-                       break;
-               case ADD_ALGO:                  //already existing algo : on father ?
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
-                       {
-                               ret = _meshDS->AddHypothesis(_subShape, anHyp);
-//        if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
-//        if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
-                               if (ret &&
-                                       (anHyp->GetShapeType() & (1 << _subShape.ShapeType())))
-                               {
-                                       SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                                       if (algo == NULL)       // two algo on the same subShape...
-                                       {
-                                               MESSAGE("two algo on the same subshape not allowed");
-                                               ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                                               ret = false;
-                                       }
-                                       else
-                                       {
-                                               ret = algo->CheckHypothesis((*_father), _subShape);
-                                               if (ret)
-                                                       SetAlgoState(HYP_OK);
-                                               else
-                                                       SetAlgoState(MISSING_HYP);
-                                       }
-                               }
-                       }
-                       break;
-               case REMOVE_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                       break;
-               case REMOVE_ALGO:               // perhaps a father algo applies ?
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-//    if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
-//    if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
-                       if (ret && (anHyp->GetShapeType() & (1 << _subShape.ShapeType())))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // no more algo applying on subShape...
-                               {
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               case ADD_FATHER_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                       }
-                       break;
-               case ADD_FATHER_ALGO:   // detect if two algo of same dim on father
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-//    if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
-//    if (anHyp->GetShapeType() == _subShape.ShapeType())
-                       if (anHyp->GetShapeType() & (1 << _subShape.ShapeType()))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // two applying algo on father
-                               {
-                                       MESSAGE("two applying algo on fatherShape...");
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               case REMOVE_FATHER_HYP: // nothing to do
-                       break;
-               case REMOVE_FATHER_ALGO:
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-//    if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
-//    if (anHyp->GetShapeType() == _subShape.ShapeType())
-                       if (anHyp->GetShapeType() & (1 << _subShape.ShapeType()))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // no more applying algo on father
-                               {
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
 
-               // ----------------------------------------------------------------------
+SMESH_Hypothesis::Hypothesis_Status
+  SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
+{
+  //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
+  //SCRUTE(_algoState);
+  //SCRUTE(event);
+
+  // **** 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;
+
+  int dim = SMESH_Gen::GetShapeDim(_subShape);
+
+  if (dim < 1)
+  {
+    _algoState = HYP_OK;
+    if (event == ADD_HYP || event == ADD_ALGO)
+      return SMESH_Hypothesis::HYP_BAD_DIM; // do not allow to assign any hyp
+    else
+      return SMESH_Hypothesis::HYP_OK;
+  }
+
+  SMESH_Gen* gen =_father->GetGen();
+//  bool ret = false;
+  int oldAlgoState = _algoState;
+  bool modifiedHyp = false;  // if set to true, force event MODIF_ALGO_STATE
+                             // in ComputeStateEngine
+
+  // ----------------------
+  // check mesh conformity
+  // ----------------------
+  if (event == ADD_ALGO)
+  {
+    if (IsApplicableHypotesis( anHyp ) &&
+        !_father->IsNotConformAllowed() &&
+        !IsConform( static_cast< SMESH_Algo* >( anHyp )))
+      return SMESH_Hypothesis::HYP_NOTCONFORM;
+  }
+
+  // ----------------------------------
+  // add a hypothesis to DS if possible
+  // ----------------------------------
+  if (event == ADD_HYP || event == ADD_ALGO)
+  {
+    if ( ! CanAddHypothesis( anHyp ))
+      return SMESH_Hypothesis::HYP_BAD_DIM;
+
+    if ( GetSimilarAttached( _subShape, anHyp ) )
+      return SMESH_Hypothesis::HYP_ALREADY_EXIST;
+
+    if ( !_meshDS->AddHypothesis(_subShape, anHyp))
+      return SMESH_Hypothesis::HYP_ALREADY_EXIST;
+
+    // Serve Propagation of 1D hypothesis
+    if (event == ADD_HYP) {
+      bool isPropagationOk = true;
+      string hypName = anHyp->GetName();
+
+      if (hypName == "Propagation") {
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current())) {
+            if (!_father->BuildPropagationChain(exp.Current())) {
+              isPropagationOk = false;
+            }
+          }
+        }
+      }
+      else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current())) {
+            TopoDS_Shape aMainEdge;
+            if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
+              isPropagationOk = _father->RebuildPropagationChains();
+            } else if (_father->IsPropagationHypothesis(exp.Current())) {
+              isPropagationOk = _father->BuildPropagationChain(exp.Current());
+            } else {
+            }
+          }
+        }
+      } else {
+      }
+
+      if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT) {
+        ret = SMESH_Hypothesis::HYP_CONCURENT;
+      }
+    } // Serve Propagation of 1D hypothesis
+  }
+
+  // --------------------------
+  // remove a hypothesis from DS
+  // --------------------------
+  if (event == REMOVE_HYP || event == REMOVE_ALGO)
+  {
+    if (!_meshDS->RemoveHypothesis(_subShape, anHyp))
+      return SMESH_Hypothesis::HYP_OK; // nothing changes
+
+    // Serve Propagation of 1D hypothesis
+    if (event == REMOVE_HYP)
+    {
+      bool isPropagationOk = true;
+      SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
+      if ( propagFilter.IsOk( anHyp, _subShape ))
+      {
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current()) &&
+              !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
+            // no more Propagation on the current edge
+            if (!_father->RemovePropagationChain(exp.Current())) {
+              return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
+            }
+          }
+        }
+        // rebuild propagation chains, because removing one
+        // chain can resolve concurention, existing before
+        isPropagationOk = _father->RebuildPropagationChains();
+      }
+      else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
+      {
+        isPropagationOk = _father->RebuildPropagationChains();
+      }
+
+      if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT) {
+        ret = SMESH_Hypothesis::HYP_CONCURENT;
+      }
+    } // Serve Propagation of 1D hypothesis
+  }
+
+  // ------------------
+  // analyse algo state
+  // ------------------
+  if (!IsApplicableHypotesis( anHyp ))
+    return ret; // not applicable hypotheses do not change algo state
+
+  switch (_algoState)
+  {
+
+    // ----------------------------------------------------------------------
+
+  case NO_ALGO:
+    switch (event) {
+    case ADD_HYP:
+      break;
+    case ADD_ALGO: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
+        SetAlgoState(HYP_OK);
+      else
+        SetAlgoState(MISSING_HYP);
+      break;
+    }
+    case REMOVE_HYP:
+      break;
+    case REMOVE_ALGO:
+      break;
+    case ADD_FATHER_HYP:
+      break;
+    case ADD_FATHER_ALGO: {    // Algo just added in father
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo == anHyp ) {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
+          SetAlgoState(HYP_OK);
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    case REMOVE_FATHER_HYP:
+      break;
+    case REMOVE_FATHER_ALGO: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if (algo)
+      {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+            SetAlgoState(HYP_OK);
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  case MISSING_HYP:
+    switch (event)
+    {
+    case ADD_HYP: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, ret ))
+        SetAlgoState(HYP_OK);
+      if (SMESH_Hypothesis::IsStatusFatal( ret ))
+        _meshDS->RemoveHypothesis(_subShape, anHyp);
+      else if (!_father->IsUsedHypothesis(  anHyp, _subShape ))
+      {
+        _meshDS->RemoveHypothesis(_subShape, anHyp);
+        ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+      }
+      break;
+    }
+    case ADD_ALGO: {           //already existing algo : on father ?
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
+        SetAlgoState(HYP_OK);
+      else
+        SetAlgoState(MISSING_HYP);
+      break;
+    }
+    case REMOVE_HYP:
+      break;
+    case REMOVE_ALGO: {        // perhaps a father algo applies ?
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if (algo == NULL)  // no more algo applying on subShape...
+      {
+        SetAlgoState(NO_ALGO);
+      }
+      else
+      {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+          SetAlgoState(HYP_OK);
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    case ADD_FATHER_HYP: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+        SetAlgoState(HYP_OK);
+      else
+        SetAlgoState(MISSING_HYP);
+    }
+      break;
+    case ADD_FATHER_ALGO: { // new father algo
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT( algo );
+      if ( algo == anHyp ) {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+          SetAlgoState(HYP_OK);
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    case REMOVE_FATHER_HYP:    // nothing to do
+      break;
+    case REMOVE_FATHER_ALGO: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if (algo == NULL)  // no more applying algo on father
+      {
+        SetAlgoState(NO_ALGO);
+      }
+      else
+      {
+        if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
+          SetAlgoState(HYP_OK);
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  case HYP_OK:
+    switch (event)
+    {
+    case ADD_HYP: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if (!algo->CheckHypothesis((*_father),_subShape, ret ))
+      {
+        if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
+          // ret should be fatal: anHyp was not added
+          ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+      }
+      else if (!_father->IsUsedHypothesis(  anHyp, _subShape ))
+        ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+
+      if (SMESH_Hypothesis::IsStatusFatal( ret ))
+      {
+        MESSAGE("do not add extra hypothesis");
+        _meshDS->RemoveHypothesis(_subShape, anHyp);
+      }
+      else
+      {
+        modifiedHyp = true;
+      }
+      break;
+    }
+    case ADD_ALGO: {           //already existing algo : on father ?
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+        // check if algo changes
+        SMESH_HypoFilter f;
+        f.Init(   SMESH_HypoFilter::IsAlgo() );
+        f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
+        f.AndNot( SMESH_HypoFilter::Is( algo ));
+        const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
+        if (prevAlgo && 
+            string(algo->GetName()) != string(prevAlgo->GetName()) )
+          modifiedHyp = true;
+      }
+      else
+        SetAlgoState(MISSING_HYP);
+      break;
+    }
+    case REMOVE_HYP: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+        SetAlgoState(HYP_OK);
+      else
+        SetAlgoState(MISSING_HYP);
+      modifiedHyp = true;
+      break;
+    }
+    case REMOVE_ALGO: {         // perhaps a father algo applies ?
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if (algo == NULL)   // no more algo applying on subShape...
+      {
+        SetAlgoState(NO_ALGO);
+      }
+      else
+      {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo remains
+          if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
+            modifiedHyp = true;
+        }
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    case ADD_FATHER_HYP: {  // new father hypothesis ?
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
+      {
+        if (_father->IsUsedHypothesis( anHyp, _subShape )) // new Hyp
+          modifiedHyp = true;
+      }
+      else
+        SetAlgoState(MISSING_HYP);
+      break;
+    }
+    case ADD_FATHER_ALGO: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if ( algo == anHyp ) { // a new algo on father
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo changes
+          SMESH_HypoFilter f;
+          f.Init(   SMESH_HypoFilter::IsAlgo() );
+          f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
+          f.AndNot( SMESH_HypoFilter::Is( algo ));
+          const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
+          if (prevAlgo && 
+              string(algo->GetName()) != string(prevAlgo->GetName()) )
+            modifiedHyp = true;
+        }
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    case REMOVE_FATHER_HYP: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      ASSERT(algo);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+        // is there the same local hyp or maybe a new father algo applied?
+        if ( !GetSimilarAttached( _subShape, anHyp ) )
+          modifiedHyp = true;
+      }
+      else
+        SetAlgoState(MISSING_HYP);
+      break;
+    }
+    case REMOVE_FATHER_ALGO: {
+      SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
+      if (algo == NULL)  // no more applying algo on father
+      {
+        SetAlgoState(NO_ALGO);
+      }
+      else
+      {
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo changes
+          if ( string(algo->GetName()) != string( anHyp->GetName()) )
+            modifiedHyp = true;
+        }
+        else
+          SetAlgoState(MISSING_HYP);
+      }
+      break;
+    }
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  default:
+    ASSERT(0);
+    break;
+  }
+
+  if ((_algoState != oldAlgoState) || modifiedHyp)
+    ComputeStateEngine(MODIF_ALGO_STATE);
+
+  return ret;
+}
 
-       case HYP_OK:
-               switch (event)
-               {
-               case ADD_HYP:
-               {
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                       ASSERT(algo);
-                       list<const SMESHDS_Hypothesis *> originalUsedHyps = algo->GetUsedHypothesis((*_father), _subShape);     // copy
-
-                       ret = _meshDS->AddHypothesis(_subShape, anHyp);
-                       if (ret)
-                       {
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (!ret)
-                               {
-                                       INFOS("two applying algo on the same shape not allowed");
-                                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                                       ret = false;
-                               }
-                               else                    // compare SMESHDS_Hypothesis* lists (order important)
-                               {
-                                       MESSAGE("---");
-                                       const list <const SMESHDS_Hypothesis *> & newUsedHyps
-                                               = algo->GetUsedHypothesis((*_father), _subShape);
-                                       modifiedHyp = (originalUsedHyps != newUsedHyps);
-                               }
-                       }
-               }
-                       break;
-               case ADD_ALGO:                  //already existing algo : on father ?
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
-                       {
-                               ret = _meshDS->AddHypothesis(_subShape, anHyp);
-//        if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
-//        if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
-                               if (ret &&
-                                       (anHyp->GetShapeType() & (1 << _subShape.ShapeType())))
-                               {
-                                       SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                                       if (algo == NULL)       // two algo on the same subShape...
-                                       {
-                                               INFOS("two algo on the same subshape not allowed");
-                                               ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                                               ret = false;
-                                       }
-                                       else
-                                       {
-                                               ret = algo->CheckHypothesis((*_father), _subShape);
-                                               if (ret)
-                                                       SetAlgoState(HYP_OK);
-                                               else
-                                                       SetAlgoState(MISSING_HYP);
-                                       }
-                               }
-                       }
-                       break;
-               case REMOVE_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-                       if (ret)
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                               modifiedHyp = true;
-                       }
-                       break;
-               case REMOVE_ALGO:               // perhaps a father algo applies ?
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
-//    if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
-//    if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
-                       if (ret && (anHyp->GetShapeType() & (1 << _subShape.ShapeType())))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // no more algo applying on subShape...
-                               {
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               case ADD_FATHER_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                       }
-                       break;
-               case ADD_FATHER_ALGO:   // detect if two algo of same dim on father
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-//    if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
-//    if (anHyp->GetShapeType() == _subShape.ShapeType())
-                       if (anHyp->GetShapeType() & (1 << _subShape.ShapeType()))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // two applying algo on father
-                               {
-                                       MESSAGE("two applying algo on fatherShape...");
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               case REMOVE_FATHER_HYP:
-                       ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               ASSERT(algo);
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       SetAlgoState(HYP_OK);
-                               else
-                                       SetAlgoState(MISSING_HYP);
-                       }
-                       break;
-               case REMOVE_FATHER_ALGO:
-                       ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
-//    if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
-//    if (anHyp->GetShapeType() == _subShape.ShapeType())
-                       if (anHyp->GetShapeType() & (1 << _subShape.ShapeType()))
-                       {
-                               SMESH_Algo *algo = gen->GetAlgo((*_father), _subShape);
-                               if (algo == NULL)       // no more applying algo on father
-                               {
-                                       SetAlgoState(NO_ALGO);
-                               }
-                               else
-                               {
-                                       ret = algo->CheckHypothesis((*_father), _subShape);
-                                       if (ret)
-                                               SetAlgoState(HYP_OK);
-                                       else
-                                               SetAlgoState(MISSING_HYP);
-                               }
-                       }
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
 
-               // ----------------------------------------------------------------------
+//=======================================================================
+//function : IsConform
+//purpose  : check if a conform mesh will be produced by the Algo
+//=======================================================================
 
-       default:
-               ASSERT(0);
-               break;
-       }
-       //SCRUTE(_algoState);
-       if ((_algoState != _oldAlgoState) || modifiedHyp)
-               int retc = ComputeStateEngine(MODIF_ALGO_STATE);
-       return ret;
+bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
+{
+//  MESSAGE( "SMESH_subMesh::IsConform" );
+
+  if ( !theAlgo ) return false;
+
+  // check only algo that doesn't NeedDescretBoundary(): because mesh made
+  // on a sub-shape will be ignored by theAlgo
+  if ( theAlgo->NeedDescretBoundary() )
+    return true;
+
+  SMESH_Gen* gen =_father->GetGen();
+
+  // only local algo is to be checked
+  if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
+    return true;
+
+  // check algo attached to adjacent shapes
+
+  // loop on one level down sub-meshes
+  TopoDS_Iterator itsub( _subShape );
+  for (; itsub.More(); itsub.Next())
+  {
+    // loop on adjacent subShapes
+    TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
+    for (; it.More(); it.Next())
+    {
+      const TopoDS_Shape& adjacent = it.Value();
+      if ( _subShape.IsSame( adjacent )) continue;
+      if ( adjacent.ShapeType() != _subShape.ShapeType())
+        break;
+
+      // check algo attached to smAdjacent
+      SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
+      if (algo &&
+          //algo != theAlgo &&
+          !algo->NeedDescretBoundary() /*&&
+          !gen->IsGlobalHypothesis( algo, *_father )*/)
+        return false; // NOT CONFORM MESH WILL BE PRODUCED
+    }
+  }
+
+  return true;
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
 void SMESH_subMesh::SetAlgoState(int state)
 {
-       if (state != _oldAlgoState)
+//     if (state != _oldAlgoState)
 //     int retc = ComputeStateEngine(MODIF_ALGO_STATE);
                _algoState = state;
 }
 
 //=============================================================================
 /*!
- * 
+ *
+ */
+//=============================================================================
+SMESH_Hypothesis::Hypothesis_Status
+  SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
+                                          SMESH_Hypothesis * anHyp)
+{
+  //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
+  SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
+  //EAP: a wire (dim==1) should notify edges (dim==1)
+  //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
+  if (/*EAP:dim > 1*/ _subShape.ShapeType() < TopAbs_EDGE )
+  {
+    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;
+      SMESH_Hypothesis::Hypothesis_Status ret2 =
+        sm->AlgoStateEngine(event, anHyp);
+      if ( ret2 > ret )
+        ret = ret2;
+    }
+  }
+  return ret;
+}
+
+//=============================================================================
+/*!
+ *
  */
 //=============================================================================
 
-void SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
-       SMESH_Hypothesis * anHyp) throw(SALOME_Exception)
+void SMESH_subMesh::CleanDependsOn()
 {
-       //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
-       int dim = SMESH_Gen::GetShapeDim(_subShape);
-       if (dim > 1)
-       {
-               const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+       MESSAGE("SMESH_subMesh::CleanDependsOn");
+       // **** parcourir les ancetres dans l'ordre de dépendance
 
-               map < int, SMESH_subMesh * >::const_iterator itsub;
-               for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-               {
-                       SMESH_subMesh *sm = (*itsub).second;
-                       sm->AlgoStateEngine(event, anHyp);
-               }
+       ComputeStateEngine(CLEAN);
+
+       const map < int, SMESH_subMesh * >&dependson = DependsOn();
+       map < int, SMESH_subMesh * >::const_iterator its;
+       for (its = dependson.begin(); its != dependson.end(); its++)
+       {
+               SMESH_subMesh *sm = (*its).second;
+               sm->ComputeStateEngine(CLEAN);
        }
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
@@ -1095,428 +1111,607 @@ void SMESH_subMesh::DumpAlgoState(bool isMain)
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
-bool SMESH_subMesh::ComputeStateEngine(int event) throw(SALOME_Exception)
+static void removeSubMesh( SMESHDS_Mesh * meshDS, const TopoDS_Shape& subShape)
 {
-       //MESSAGE("SMESH_subMesh::ComputeStateEngine");
-       //SCRUTE(_computeState);
-       //SCRUTE(event);
-
-       int dim = SMESH_Gen::GetShapeDim(_subShape);
-
-       if (dim < 1)
-       {
-               if (_vertexSet)
-                       _computeState = COMPUTE_OK;
-               else
-                       _computeState = READY_TO_COMPUTE;
-               //SCRUTE(_computeState);
-               return true;
-       }
-       SMESH_Gen *gen = _father->GetGen();
-       SMESH_Algo *algo = 0;
-       bool ret;
-
-       switch (_computeState)
-       {
-
-               // ----------------------------------------------------------------------
+  SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(subShape);
+  if (subMeshDS!=NULL)
+  {
+    SMDS_ElemIteratorPtr ite=subMeshDS->GetElements();
+    while(ite->more())
+    {
+      const SMDS_MeshElement * elt = ite->next();
+      //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
+      meshDS->RemoveElement(elt);
+    }
+
+    SMDS_NodeIteratorPtr itn=subMeshDS->GetNodes();
+    while(itn->more())
+    {
+      const SMDS_MeshNode * node = itn->next();
+      //MESSAGE( " RM node: "<<node->GetID());
+      meshDS->RemoveNode(node);
+    }
+  }
+}
 
-       case NOT_READY:
-               switch (event)
-               {
-               case MODIF_HYP:         // nothing to do
-                       break;
-               case MODIF_ALGO_STATE:
-                       if (_algoState == HYP_OK)
-                               _computeState = READY_TO_COMPUTE;
-                       break;
-               case COMPUTE:                   // nothing to do
-                       break;
-               case CLEAN:                     // nothing to do
-                       break;
-               case CLEANDEP:                  // nothing to do
-                       RemoveSubMeshElementsAndNodes();        // recursive call...
-                       break;
-               case SUBMESH_COMPUTED:  // nothing to do
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
 
-               // ----------------------------------------------------------------------
+bool SMESH_subMesh::ComputeStateEngine(int event)
+{
+  //MESSAGE("SMESH_subMesh::ComputeStateEngine");
+  //SCRUTE(_computeState);
+  //SCRUTE(event);
+
+  int dim = SMESH_Gen::GetShapeDim(_subShape);
+
+  if (dim < 1)
+  {
+    if ( IsMeshComputed() )
+      _computeState = COMPUTE_OK;
+    else
+      _computeState = READY_TO_COMPUTE;
+    return true;
+  }
+  SMESH_Gen *gen = _father->GetGen();
+  SMESH_Algo *algo = 0;
+  bool ret = true;
+  SMESH_Hypothesis::Hypothesis_Status hyp_status;
+
+  switch (_computeState)
+  {
+
+    // ----------------------------------------------------------------------
+
+  case NOT_READY:
+    switch (event)
+    {
+    case MODIF_HYP:            // nothing to do
+      break;
+    case MODIF_ALGO_STATE:
+      if (_algoState == HYP_OK)
+      {
+        _computeState = READY_TO_COMPUTE;
+      }
+      break;
+    case COMPUTE:                      // nothing to do
+      break;
+    case CLEAN:
+      RemoveSubMeshElementsAndNodes();
+      break;
+    case CLEANDEP:
+      CleanDependants();
+      break;
+    case SUBMESH_COMPUTED:     // nothing to do
+      break;
+    case SUBMESH_RESTORED:
+      ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+      break;
+    case MESH_ENTITY_REMOVED:
+      break;
+    case CHECK_COMPUTE_STATE:
+      if ( IsMeshComputed() )
+        _computeState = COMPUTE_OK;
+      break;
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  case READY_TO_COMPUTE:
+    switch (event)
+    {
+    case MODIF_HYP:            // nothing to do
+      break;
+    case MODIF_ALGO_STATE:
+      _computeState = NOT_READY;
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo)
+      {
+        ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+        if (ret)
+          _computeState = READY_TO_COMPUTE;
+      }
+      break;
+    case COMPUTE:
+      {
+        algo = gen->GetAlgo((*_father), _subShape);
+        ASSERT(algo);
+        ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+        if (!ret)
+        {
+          MESSAGE("***** verify compute state *****");
+          _computeState = NOT_READY;
+          break;
+        }
+        // check submeshes needed
+        if (algo->NeedDescretBoundary())
+          ret = SubMeshesComputed();
+        if (!ret)
+        {
+          MESSAGE("Some SubMeshes not computed");
+          _computeState = FAILED_TO_COMPUTE;
+          break;
+        }
+        // compute
+        RemoveSubMeshElementsAndNodes();
+        //removeSubMesh( _meshDS, _subShape );
+        if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
+          ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
+        else
+          ret = algo->Compute((*_father), _subShape);
+
+        if (!ret)
+        {
+          MESSAGE("problem in algo execution: failed to compute");
+          _computeState = FAILED_TO_COMPUTE;
+          if (!algo->NeedDescretBoundary())
+            UpdateSubMeshState( FAILED_TO_COMPUTE );
+
+#ifdef _DEBUG_
+          // Show vertices location of a failed shape
+          TopTools_IndexedMapOfShape vMap;
+          TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
+          for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
+            gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
+            cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
+          }
+#endif
+          break;
+        }
+        else
+        {
+          _computeState = COMPUTE_OK;
+          UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
+          if (!algo->NeedDescretBoundary())
+            UpdateSubMeshState( COMPUTE_OK );
+        }
+      }
+      break;
+    case CLEAN:
+      RemoveSubMeshElementsAndNodes();
+      _computeState = NOT_READY;
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo)
+      {
+        ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+        if (ret)
+          _computeState = READY_TO_COMPUTE;
+      }
+      break;
+    case CLEANDEP:
+      CleanDependants();
+      break;
+    case SUBMESH_COMPUTED:      // nothing to do
+      break;
+    case SUBMESH_RESTORED:
+      // check if a mesh is already computed that may
+      // happen after retrieval from a file
+      ComputeStateEngine( CHECK_COMPUTE_STATE );
+      ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+      break;
+    case MESH_ENTITY_REMOVED:
+      break;
+    case CHECK_COMPUTE_STATE:
+      if ( IsMeshComputed() )
+        _computeState = COMPUTE_OK;
+      break;
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  case COMPUTE_OK:
+    switch (event)
+    {
+    case MODIF_HYP:
+      CleanDependants();        // recursive recall with event CLEANDEP
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo && !algo->NeedDescretBoundary())
+        CleanDependsOn(); // remove sub-mesh with event CLEANDEP
+      break;
+    case MODIF_ALGO_STATE:
+      CleanDependants();        // recursive recall with event CLEANDEP
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo && !algo->NeedDescretBoundary())
+        CleanDependsOn(); // remove sub-mesh with event CLEANDEP
+      break;
+    case COMPUTE:                       // nothing to do
+      break;
+    case CLEAN:
+      RemoveSubMeshElementsAndNodes();
+      _computeState = NOT_READY;
+      algo = gen->GetAlgo((*_father), _subShape);
+      if (algo)
+      {
+        ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+        if (ret)
+          _computeState = READY_TO_COMPUTE;
+      }
+      break;
+    case CLEANDEP:
+      CleanDependants();        // recursive recall with event CLEANDEP
+      break;
+    case SUBMESH_COMPUTED:      // nothing to do
+      break;
+    case SUBMESH_RESTORED:
+      ComputeStateEngine( CHECK_COMPUTE_STATE );
+      ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+      break;
+    case MESH_ENTITY_REMOVED:
+      UpdateDependantsState( CHECK_COMPUTE_STATE );
+      ComputeStateEngine( CHECK_COMPUTE_STATE );
+      ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+      break;
+    case CHECK_COMPUTE_STATE:
+      if ( !IsMeshComputed() )
+        if (_algoState == HYP_OK)
+          _computeState = READY_TO_COMPUTE;
+        else
+          _computeState = NOT_READY;
+      break;
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+
+  case FAILED_TO_COMPUTE:
+    switch (event)
+    {
+    case MODIF_HYP:
+      if (_algoState == HYP_OK)
+        _computeState = READY_TO_COMPUTE;
+      else
+        _computeState = NOT_READY;
+      break;
+    case MODIF_ALGO_STATE:
+      if (_algoState == HYP_OK)
+        _computeState = READY_TO_COMPUTE;
+      else
+        _computeState = NOT_READY;
+      break;
+    case COMPUTE:      // nothing to do
+      break;
+    case CLEAN:
+      RemoveSubMeshElementsAndNodes();
+      if (_algoState == HYP_OK)
+        _computeState = READY_TO_COMPUTE;
+      else
+        _computeState = NOT_READY;
+      break;
+    case CLEANDEP:
+      CleanDependants();
+      break;
+    case SUBMESH_COMPUTED:      // allow retry compute
+      if (_algoState == HYP_OK)
+        _computeState = READY_TO_COMPUTE;
+      else
+        _computeState = NOT_READY;
+      break;
+    case SUBMESH_RESTORED:
+      ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+      break;
+    case MESH_ENTITY_REMOVED:
+      break;
+    case CHECK_COMPUTE_STATE:
+      if ( IsMeshComputed() )
+        _computeState = COMPUTE_OK;
+      else
+        if (_algoState == HYP_OK)
+          _computeState = READY_TO_COMPUTE;
+        else
+          _computeState = NOT_READY;
+      break;
+    default:
+      ASSERT(0);
+      break;
+    }
+    break;
+
+    // ----------------------------------------------------------------------
+  default:
+    ASSERT(0);
+    break;
+  }
+
+  //SCRUTE(_computeState);
+  return ret;
+}
 
-       case READY_TO_COMPUTE:
-               switch (event)
-               {
-               case MODIF_HYP:         // nothing to do
-                       break;
-               case MODIF_ALGO_STATE:
-                       _computeState = NOT_READY;
-                       algo = gen->GetAlgo((*_father), _subShape);
-                       if (algo)
-                       {
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       _computeState = READY_TO_COMPUTE;
-                       }
-                       break;
-               case COMPUTE:
-               {
-                       algo = gen->GetAlgo((*_father), _subShape);
-                       ASSERT(algo);
-                       ret = algo->CheckHypothesis((*_father), _subShape);
-                       if (!ret)
-                       {
-                               MESSAGE("***** verify compute state *****");
-                               _computeState = NOT_READY;
-                               break;
-                       }
-                       ret = SubMeshesComputed();
-                       if (!ret)
-                       {
-                               MESSAGE("Some SubMeshes not computed");
-                               _computeState = FAILED_TO_COMPUTE;
-                               break;
-                       }
-                       ret = algo->Compute((*_father), _subShape);
-                       if (!ret)
-                       {
-                               MESSAGE("problem in algo execution: failed to compute");
-                               _computeState = FAILED_TO_COMPUTE;
-                               break;
-                       }
-                       else
-                       {
-                               _computeState = COMPUTE_OK;
-                               UpdateDependantsState();        // send event SUBMESH_COMPUTED
-                       }
-               }
-                       break;
-               case CLEAN:
-                       _computeState = NOT_READY;
-                       algo = gen->GetAlgo((*_father), _subShape);
-                       if (algo)
-                       {
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       _computeState = READY_TO_COMPUTE;
-                       }
-                       break;
-               case CLEANDEP:
-                       RemoveSubMeshElementsAndNodes();
-                       _computeState = NOT_READY;
-                       algo = gen->GetAlgo((*_father), _subShape);
-                       if (algo)
-                       {
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       _computeState = READY_TO_COMPUTE;
-                       }
-                       break;
-               case SUBMESH_COMPUTED:  // nothing to do
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
+//=======================================================================
+//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() );
+
+  bool ret = false;
+
+
+  ret = theAlgo->Compute( *_father, theCollection );
+
+  // set _computeState of subshapes
+  TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
+  for ( ; anExplorer.More(); anExplorer.Next() )
+  {
+    const TopoDS_Shape& aSubShape = anExplorer.Current();
+    SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
+    if ( subMesh )
+    {
+      if (ret)
+      {
+        subMesh->_computeState = COMPUTE_OK;
+        subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
+        subMesh->UpdateSubMeshState( COMPUTE_OK );
+      }
+      else
+      {
+        subMesh->_computeState = FAILED_TO_COMPUTE;
+      }
+    }
+  }
+  return ret;
+}
 
-       case COMPUTE_OK:
-               switch (event)
-               {
-               case MODIF_HYP:
-                       CleanDependants();      // recursive recall with event CLEANDEP
-                       break;
-               case MODIF_ALGO_STATE:
-                       CleanDependants();      // recursive recall with event CLEANDEP
-                       break;
-               case COMPUTE:                   // nothing to do
-                       break;
-               case CLEAN:
-                       CleanDependants();      // recursive recall with event CLEANDEP
-                       break;
-               case CLEANDEP:
-                       RemoveSubMeshElementsAndNodes();
-                       _computeState = NOT_READY;
-                       algo = gen->GetAlgo((*_father), _subShape);
-                       if (algo)
-                       {
-                               ret = algo->CheckHypothesis((*_father), _subShape);
-                               if (ret)
-                                       _computeState = READY_TO_COMPUTE;
-                       }
-                       break;
-               case SUBMESH_COMPUTED:  // nothing to do
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
 
-               // ----------------------------------------------------------------------
+//=======================================================================
+//function : UpdateSubMeshState
+//purpose  :
+//=======================================================================
 
-       case FAILED_TO_COMPUTE:
-               switch (event)
-               {
-               case MODIF_HYP:
-                       if (_algoState == HYP_OK)
-                               _computeState = READY_TO_COMPUTE;
-                       else
-                               _computeState = NOT_READY;
-                       break;
-               case MODIF_ALGO_STATE:
-                       if (_algoState == HYP_OK)
-                               _computeState = READY_TO_COMPUTE;
-                       else
-                               _computeState = NOT_READY;
-                       break;
-               case COMPUTE:                   // nothing to do
-                       break;
-               case CLEAN:
-                       break;
-               case CLEANDEP:
-                       RemoveSubMeshElementsAndNodes();
-                       if (_algoState == HYP_OK)
-                               _computeState = READY_TO_COMPUTE;
-                       else
-                               _computeState = NOT_READY;
-                       break;
-               case SUBMESH_COMPUTED:  // allow retry compute
-                       if (_algoState == HYP_OK)
-                               _computeState = READY_TO_COMPUTE;
-                       else
-                               _computeState = NOT_READY;
-                       break;
-               default:
-                       ASSERT(0);
-                       break;
-               }
-               break;
+void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
+{
+  const map<int, SMESH_subMesh*>& smMap = DependsOn();
+  map<int, SMESH_subMesh*>::const_iterator itsub;
+  for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
+  {
+    SMESH_subMesh* sm = (*itsub).second;
+    sm->_computeState = theState;
+  }
+}
 
-               // ----------------------------------------------------------------------
-       default:
-               ASSERT(0);
-               break;
-       }
+//=======================================================================
+//function : ComputeSubMeshStateEngine
+//purpose  :
+//=======================================================================
 
-       //SCRUTE(_computeState);
-       return ret;
+void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
+{
+  const map<int, SMESH_subMesh*>& smMap = DependsOn();
+  map<int, SMESH_subMesh*>::const_iterator itsub;
+  for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
+  {
+    SMESH_subMesh* sm = (*itsub).second;
+    sm->ComputeStateEngine(event);
+  }
 }
 
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
+//=======================================================================
+//function : UpdateDependantsState
+//purpose  :
+//=======================================================================
 
-void SMESH_subMesh::UpdateDependantsState()
+void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
 {
-       //MESSAGE("SMESH_subMesh::UpdateDependantsState");
-
-       const map < int, SMESH_subMesh * >&dependants = Dependants();
-       map < int, SMESH_subMesh * >::const_iterator its;
-       for (its = dependants.begin(); its != dependants.end(); its++)
-       {
-               SMESH_subMesh *sm = (*its).second;
-               //SCRUTE((*its).first);
-               sm->ComputeStateEngine(SUBMESH_COMPUTED);
-       }
+  //MESSAGE("SMESH_subMesh::UpdateDependantsState");
+  TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
+  for (; it.More(); it.Next())
+  {
+    const TopoDS_Shape& ancestor = it.Value();
+    SMESH_subMesh *aSubMesh =
+      _father->GetSubMeshContaining(ancestor);
+    if (aSubMesh)
+      aSubMesh->ComputeStateEngine( theEvent );
+  }
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
 void SMESH_subMesh::CleanDependants()
 {
-       MESSAGE("SMESH_subMesh::CleanDependants");
-       // **** parcourir les ancetres dans l'ordre de dépendance
-
-       const map < int, SMESH_subMesh * >&dependants = Dependants();
-       map < int, SMESH_subMesh * >::const_iterator its;
-       for (its = dependants.begin(); its != dependants.end(); its++)
-       {
-               SMESH_subMesh *sm = (*its).second;
-               SCRUTE((*its).first);
-               sm->ComputeStateEngine(CLEANDEP);
-       }
-       ComputeStateEngine(CLEANDEP);
+  TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
+  for (; it.More(); it.Next())
+  {
+    const TopoDS_Shape& ancestor = it.Value();
+    // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEANDEP)
+    // will erase mesh on other shapes in a compound
+    if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
+      SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
+      if (aSubMesh)
+        aSubMesh->ComputeStateEngine(CLEANDEP);
+    }
+  }
+  ComputeStateEngine(CLEAN);
 }
 
 //=============================================================================
 /*!
- * 
+ *
  */
 //=============================================================================
 
 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
 {
-       MESSAGE("SMESH_subMesh::RemoveSubMeshElementsAndNodes");
-       SCRUTE(_subShape.ShapeType());
-       SCRUTE(_Id);
+  //SCRUTE(_subShape.ShapeType());
+
+  removeSubMesh( _meshDS, _subShape );
+
+  // algo may bind a submesh not to _subShape, eg 3D algo
+  // sets nodes on SHELL while _subShape may be SOLID
+
+  int dim = SMESH_Gen::GetShapeDim( _subShape );
+  int type = _subShape.ShapeType() + 1;
+  for ( ; type <= TopAbs_EDGE; type++)
+    if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
+    {
+      TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
+      for ( ; exp.More(); exp.Next() )
+        removeSubMesh( _meshDS, exp.Current() );
+    }
+    else
+      break;
+}
 
-       _subMeshDS = _meshDS->MeshElements(_subShape);
-       if (_subMeshDS!=NULL)
-       {
-               SMDS_Iterator<const SMDS_MeshElement *> * ite=_subMeshDS->GetElements();
-               while(ite->more())
-               {
-                       const SMDS_MeshElement * elt = ite->next();
-                       _subMeshDS->RemoveElement(elt);
-                       _meshDS->RemoveElement(elt);
-               }
-               delete ite;
-               
-               SMDS_Iterator<const SMDS_MeshNode *> * itn=_subMeshDS->GetNodes();
-               while(itn->more())
-               {
-                       const SMDS_MeshNode * node = itn->next();
-                       _subMeshDS->RemoveNode(node);
-                       _meshDS->RemoveNode(node);
-               }
-               delete itn;
-       }
+//=======================================================================
+//function : IsMeshComputed
+//purpose  : check if _subMeshDS contains mesh elements
+//=======================================================================
+
+bool SMESH_subMesh::IsMeshComputed() const
+{
+  // algo may bind a submesh not to _subShape, eg 3D algo
+  // sets nodes on SHELL while _subShape may be SOLID
+
+  int dim = SMESH_Gen::GetShapeDim( _subShape );
+  int type = _subShape.ShapeType();
+  for ( ; type <= TopAbs_VERTEX; type++) {
+    if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
+    {
+      TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
+      for ( ; exp.More(); exp.Next() )
+      {
+        SMESHDS_SubMesh * subMeshDS = _meshDS->MeshElements( exp.Current() );
+        if ( subMeshDS != NULL &&
+            (subMeshDS->GetElements()->more() || subMeshDS->GetNodes()->more())) {
+          return true;
+        }
+      }
+    }
+    else
+      break;
+  }
+
+  return false;
 }
 
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
 
-const map < int, SMESH_subMesh * >&SMESH_subMesh::Dependants()
+//=======================================================================
+//function : GetCollection
+//purpose  : return a shape containing all sub-shapes of the MainShape that can be
+//           meshed at once along with _subShape
+//=======================================================================
+
+TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
 {
-       if (_dependantsFound)
-               return _mapDependants;
+  MESSAGE("SMESH_subMesh::GetCollection");
+  ASSERT (!theAlgo->NeedDescretBoundary());
 
-       //MESSAGE("SMESH_subMesh::Dependants");
+  TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
 
-       int shapeType = _subShape.ShapeType();
-       //SCRUTE(shapeType);
-       TopTools_IndexedDataMapOfShapeListOfShape M;
-       TopoDS_Shape mainShape = _meshDS->ShapeToMesh();
+  if ( mainShape.IsSame( _subShape ))
+    return _subShape;
 
-       switch (shapeType)
-       {
-       case TopAbs_VERTEX:
-               break;
-       case TopAbs_EDGE:
-       case TopAbs_WIRE:
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_WIRE, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_FACE, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_SHELL, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_SOLID, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_COMPSOLID,
-                       M);
-               ExtractDependants(M, TopAbs_EDGE);
-               break;
-       case TopAbs_FACE:
-       case TopAbs_SHELL:
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_SHELL, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_SOLID, M);
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_COMPSOLID,
-                       M);
-               ExtractDependants(M, TopAbs_FACE);
-               break;
-       case TopAbs_SOLID:
-       case TopAbs_COMPSOLID:
-               TopExp::MapShapesAndAncestors(mainShape, TopAbs_SOLID, TopAbs_COMPSOLID,
-                       M);
-               ExtractDependants(M, TopAbs_SOLID);
-               break;
-       case TopAbs_COMPOUND:
-               break;
-       }
+  list<const SMESHDS_Hypothesis*> aUsedHyp =
+    theAlgo->GetUsedHypothesis( *_father, _subShape ); // copy
 
-       _dependantsFound = true;
-       return _mapDependants;
-}
+  // put in a compound all shapes with the same hypothesis assigned
+  // and a good ComputState
 
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
+  TopoDS_Compound aCompound;
+  BRep_Builder aBuilder;
+  aBuilder.MakeCompound( aCompound );
+
+  TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
+  for ( ; anExplorer.More(); anExplorer.Next() )
+  {
+    const TopoDS_Shape& S = anExplorer.Current();
+    SMESH_subMesh* subMesh = _father->GetSubMesh( S );
+    SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
+
+    if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
+        anAlgo == theAlgo &&
+        anAlgo->GetUsedHypothesis( *_father, S ) == aUsedHyp)
+    {
+      aBuilder.Add( aCompound, S );
+    }
+  }
 
-void SMESH_subMesh::
-ExtractDependants(const TopTools_IndexedDataMapOfShapeListOfShape & M,
-       const TopAbs_ShapeEnum etype)
+  return aCompound;
+}
+
+//=======================================================================
+//function : GetSimilarAttached
+//purpose  : return nb of hypotheses attached to theShape.
+//           If theHyp is provided, similar but not same hypotheses
+//           are countered; else only applicable ones having theHypType
+//           are countered
+//=======================================================================
+
+const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
+                                                          const SMESH_Hypothesis * theHyp,
+                                                          const int                theHypType)
 {
-       //MESSAGE("SMESH_subMesh::ExtractDependants");
+  SMESH_HypoFilter filter;
+  filter.Init( SMESH_HypoFilter::HasType( theHyp ? theHyp->GetType() : theHypType ));
+  if ( theHyp ) {
+    filter.And( SMESH_HypoFilter::HasDim( theHyp->GetDim() ));
+    filter.AndNot( SMESH_HypoFilter::Is( theHyp ));
+  }
+  else
+    filter.And( SMESH_HypoFilter::IsApplicableTo( theShape ));
+
+  return _father->GetHypothesis( theShape, filter, false );
+}
 
-       TopoDS_Shape mainShape = _meshDS->ShapeToMesh();
-       int lg = M.Extent();
-       //SCRUTE(lg);
+//=======================================================================
+//function : CheckConcurentHypothesis
+//purpose  : check if there are several applicable hypothesis attached to
+//           ansestors
+//=======================================================================
 
-       int shapeType = _subShape.ShapeType();
-       switch (shapeType)
-       {
-       case TopAbs_VERTEX:
-               break;
-       case TopAbs_EDGE:
-       case TopAbs_FACE:
-       case TopAbs_SOLID:
-       {
-               const TopTools_ListOfShape & ancestors = M.FindFromKey(_subShape);
-               TopTools_ListIteratorOfListOfShape it(ancestors);
-               for (; it.More(); it.Next())
-               {
-                       TopoDS_Shape ancestor = it.Value();
-                       SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
-                       //      if (! aSubMesh) aSubMesh = _father->GetSubMesh(ancestor);
-                       if (aSubMesh)
-                       {
-                               int type = aSubMesh->_subShape.ShapeType();
-                               int cle = aSubMesh->GetId();
-                               cle += 10000000 * type; // sort map by ordType then index
-                               if (_mapDependants.find(cle) == _mapDependants.end())
-                               {
-                                       _mapDependants[cle] = aSubMesh;
-                                       //SCRUTE(cle);
-                               }
-                       }
-               }
-       }
-               break;
-       case TopAbs_WIRE:
-       case TopAbs_SHELL:
-       case TopAbs_COMPSOLID:
-               for (TopExp_Explorer expE(_subShape, etype); expE.More(); expE.Next())
-               {
-                       TopoDS_Shape aShape = expE.Current();
-                       const TopTools_ListOfShape & ancestors = M.FindFromKey(aShape);
-                       TopTools_ListIteratorOfListOfShape it(ancestors);
-                       for (; it.More(); it.Next())
-                       {
-                               MESSAGE("---");
-                               TopoDS_Shape ancestor = it.Value();
-                               SMESH_subMesh *aSubMesh =
-                                       _father->GetSubMeshContaining(ancestor);
-                               if (!aSubMesh)
-                                       aSubMesh = _father->GetSubMesh(ancestor);
-                               int type = aSubMesh->_subShape.ShapeType();
-                               int cle = aSubMesh->GetId();
-                               cle += 10000000 * type; // sort map by ordType then index
-                               if (_mapDependants.find(cle) == _mapDependants.end())
-                               {
-                                       _mapDependants[cle] = aSubMesh;
-                                       SCRUTE(cle);
-                               }
-                       }
-               }
-               break;
-       case TopAbs_COMPOUND:
-               break;
-       }
+SMESH_Hypothesis::Hypothesis_Status
+  SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
+{
+  MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
+
+  // is there local hypothesis on me?
+  if ( GetSimilarAttached( _subShape, 0, theHypType ) )
+    return SMESH_Hypothesis::HYP_OK;
+
+
+  TopoDS_Shape aPrevWithHyp;
+  const SMESH_Hypothesis* aPrevHyp = 0;
+  TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
+  for (; it.More(); it.Next())
+  {
+    const TopoDS_Shape& ancestor = it.Value();
+    const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
+    if ( hyp )
+    {
+      if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
+      {
+        aPrevWithHyp = ancestor;
+        aPrevHyp     = hyp;
+      }
+      else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
+        return SMESH_Hypothesis::HYP_CONCURENT;
+      else
+        return SMESH_Hypothesis::HYP_OK;
+    }
+  }
+  return SMESH_Hypothesis::HYP_OK;
 }