Salome HOME
0020028: EDF 842 SMESH : Can't export to med a mesh with same names
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index a4b5f80af0208839134f0186cbbaf490fe628adb..d39700ed360a2600e4a38aedbf9f059f0d65b4b4 100644 (file)
@@ -1,31 +1,29 @@
-//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  Copyright (C) 2003  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 
+//  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_Mesh.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//  $Header$
-
+//
 #include "SMESH_Mesh.hxx"
 #include "SMESH_subMesh.hxx"
 #include "SMESH_Gen.hxx"
@@ -35,7 +33,9 @@
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Script.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
+#include "SMESHDS_Document.hxx"
 #include "SMDS_MeshVolume.hxx"
+#include "SMDS_SetIterator.hxx"
 
 #include "utilities.h"
 
 #include "DriverUNV_R_SMDS_Mesh.h"
 #include "DriverSTL_R_SMDS_Mesh.h"
 
-#include <BRepTools_WireExplorer.hxx>
-#include <BRep_Builder.hxx>
-#include <gp_Pnt.hxx>
-
-#include <TCollection_AsciiString.hxx>
+#undef _Precision_HeaderFile
+#include <BRepBndLib.hxx>
+#include <BRepPrimAPI_MakeBox.hxx>
+#include <Bnd_Box.hxx>
 #include <TopExp.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_Array1OfShape.hxx>
+#include <TopExp_Explorer.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
-
-#include <memory>
+#include <TopoDS_Iterator.hxx>
 
 #include "Utils_ExceptHandlers.hxx"
 
+using namespace std;
+
+// maximum stored group name length in MED file
+#define MAX_MED_GROUP_NAME_LENGTH 80
+
 #ifdef _DEBUG_
 static int MYDEBUG = 0;
 #else
 static int MYDEBUG = 0;
 #endif
 
+#define cSMESH_Hyp(h) static_cast<const SMESH_Hypothesis*>(h)
+
+typedef SMESH_HypoFilter THypType;
 
 //=============================================================================
 /*!
@@ -76,17 +82,24 @@ static int MYDEBUG = 0;
  */
 //=============================================================================
 
-SMESH_Mesh::SMESH_Mesh(int localId, int studyId, SMESH_Gen * gen, SMESHDS_Document * myDocument)
-: _groupId( 0 )
+SMESH_Mesh::SMESH_Mesh(int               theLocalId, 
+                       int               theStudyId, 
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument):
+  _groupId( 0 ), _nbSubShapes( 0 )
 {
-  INFOS("SMESH_Mesh::SMESH_Mesh(int localId)");
-       _id = localId;
-       _studyId = studyId;
-       _gen = gen;
-       _myDocument = myDocument;
-       _idDoc = _myDocument->NewMesh();
-       _myMeshDS = _myDocument->GetMesh(_idDoc);
-       _isShapeToMesh = false;
+  MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
+  _id            = theLocalId;
+  _studyId       = theStudyId;
+  _gen           = theGen;
+  _myDocument    = theDocument;
+  _idDoc         = theDocument->NewMesh(theIsEmbeddedMode);
+  _myMeshDS      = theDocument->GetMesh(_idDoc);
+  _isShapeToMesh = false;
+  _isAutoColor   = false;
+  _shapeDiagonal = 0.0;
+  _myMeshDS->ShapeToMesh( PseudoShape() );
 }
 
 //=============================================================================
@@ -99,17 +112,23 @@ SMESH_Mesh::~SMESH_Mesh()
 {
   INFOS("SMESH_Mesh::~SMESH_Mesh");
 
+  // issue 0020340: EDF 1022 SMESH : Crash with FindNodeClosestTo in a second new study
+  //   Notify event listeners at least that something happens
+  if ( SMESH_subMesh * sm = GetSubMeshContaining(1))
+    sm->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
+
   // delete groups
   map < int, SMESH_Group * >::iterator itg;
   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
     SMESH_Group *aGroup = (*itg).second;
     delete aGroup;
   }
+  _mapGroup.clear();
 }
 
 //=============================================================================
 /*!
- * 
+ * \brief Set geometry to be meshed
  */
 //=============================================================================
 
@@ -117,7 +136,13 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
 {
   if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh");
 
-  if ( !_myMeshDS->ShapeToMesh().IsNull() && aShape.IsNull() )
+  if ( !aShape.IsNull() && _isShapeToMesh ) {
+    if ( aShape.ShapeType() != TopAbs_COMPOUND && // group contents is allowed to change
+         _myMeshDS->ShapeToMesh().ShapeType() != TopAbs_COMPOUND )
+      throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
+  }
+  // clear current data
+  if ( !_myMeshDS->ShapeToMesh().IsNull() )
   {
     // removal of a shape to mesh, delete objects referring to sub-shapes:
     // - sub-meshes
@@ -136,28 +161,178 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
       else
         i_gr++;
     }
-    _mapPropagationChains.Clear();
+    _mapAncestors.Clear();
+
+    // clear SMESHDS
+    TopoDS_Shape aNullShape;
+    _myMeshDS->ShapeToMesh( aNullShape );
+
+    _shapeDiagonal = 0.0;
+  }
+
+  // set a new geometry
+  if ( !aShape.IsNull() )
+  {
+    _myMeshDS->ShapeToMesh(aShape);
+    _isShapeToMesh = true;
+    _nbSubShapes = _myMeshDS->MaxShapeIndex();
+
+    // fill map of ancestors
+    fillAncestorsMap(aShape);
   }
   else
   {
-    if (_isShapeToMesh)
-      throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
+    _isShapeToMesh = false;
+    _shapeDiagonal = 0.0;
+    _myMeshDS->ShapeToMesh( PseudoShape() );
   }
-  _isShapeToMesh = true;
-  _myMeshDS->ShapeToMesh(aShape);
+}
 
-  // fill _mapAncestors
-  _mapAncestors.Clear();
-  int desType, ancType;
-  for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- )
-    for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
-      TopExp::MapShapesAndAncestors ( aShape,
-                                     (TopAbs_ShapeEnum) desType,
-                                     (TopAbs_ShapeEnum) ancType,
-                                     _mapAncestors );
+//=======================================================================
+/*!
+ * \brief Return geometry to be meshed. (It may be a PseudoShape()!)
+ */
+//=======================================================================
+
+TopoDS_Shape SMESH_Mesh::GetShapeToMesh() const
+{
+  return _myMeshDS->ShapeToMesh();
+}
+
+//=======================================================================
+/*!
+ * \brief Return a solid which is returned by GetShapeToMesh() if
+ *        a real geometry to be meshed was not set
+ */
+//=======================================================================
+
+const TopoDS_Solid& SMESH_Mesh::PseudoShape()
+{
+  static TopoDS_Solid aSolid;
+  if ( aSolid.IsNull() )
+  {
+    aSolid = BRepPrimAPI_MakeBox(1,1,1);
+  }
+  return aSolid;
+}
+
+//=======================================================================
+/*!
+ * \brief Return diagonal size of bounding box of a shape
+ */
+//=======================================================================
+
+double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
+{
+  if ( !aShape.IsNull() ) {
+    Bnd_Box Box;
+    BRepBndLib::Add(aShape, Box);
+    return sqrt( Box.SquareExtent() );
+  }
+  return 0;
+}
+
+//=======================================================================
+/*!
+ * \brief Return diagonal size of bounding box of shape to mesh
+ */
+//=======================================================================
+
+double SMESH_Mesh::GetShapeDiagonalSize() const
+{
+  if ( _shapeDiagonal == 0. && _isShapeToMesh )
+    const_cast<SMESH_Mesh*>(this)->_shapeDiagonal = GetShapeDiagonalSize( GetShapeToMesh() );
 
-  // NRI : 24/02/03
-  //EAP: 1/9/04 TopExp::MapShapes(aShape, _subShapes); USE the same map of _myMeshDS
+  return _shapeDiagonal;
+}
+
+//=======================================================================
+/*!
+ * \brief Remove all nodes and elements
+ */
+//=======================================================================
+
+void SMESH_Mesh::Clear()
+{
+  // clear mesh data
+  _myMeshDS->ClearMesh();
+
+  // update compute state of submeshes
+  if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) {
+    SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
+                                                             /*complexShapeFirst=*/false);
+    while ( smIt->more() ) {
+      sm = smIt->next();
+      sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    }
+  }
+
+//   // clear sub-meshes; get ready to re-compute as a side-effect 
+
+//   if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) )
+//   {
+//     SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
+//                                                              /*complexShapeFirst=*/false);
+//     while ( smIt->more() )
+//     {
+//       sm = smIt->next();
+//       TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();      
+//       if ( shapeType == TopAbs_VERTEX || shapeType < TopAbs_SOLID )
+//         // all other shapes depends on vertices so they are already cleaned
+//         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
+//       // to recompute even if failed
+//       sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+//     }
+//   }
+
+//   // clear entities not on sub-meshes
+
+//   SMDS_VolumeIteratorPtr vIt = _myMeshDS->volumesIterator();
+//   while ( vIt->more() )
+//     _myMeshDS->RemoveFreeElement( vIt->next(), 0 );
+
+//   SMDS_FaceIteratorPtr fIt = _myMeshDS->facesIterator();
+//   while ( fIt->more() )
+//     _myMeshDS->RemoveFreeElement( fIt->next(), 0 );
+
+//   SMDS_EdgeIteratorPtr eIt = _myMeshDS->edgesIterator();
+//   while ( eIt->more() )
+//     _myMeshDS->RemoveFreeElement( eIt->next(), 0 );
+
+//   SMDS_NodeIteratorPtr nIt = _myMeshDS->nodesIterator();
+//   while ( nIt->more() ) {
+//     const SMDS_MeshNode * node = nIt->next();
+//     if ( node->NbInverseElements() == 0 )
+//       _myMeshDS->RemoveFreeNode( node, 0 );
+//     else
+//       _myMeshDS->RemoveNode(node);
+//   }
+}
+
+//=======================================================================
+/*!
+ * \brief Remove all nodes and elements of indicated shape
+ */
+//=======================================================================
+
+void SMESH_Mesh::ClearSubMesh(const int theShapeId)
+{
+  // clear sub-meshes; get ready to re-compute as a side-effect 
+  if ( SMESH_subMesh *sm = GetSubMeshContaining( theShapeId ) )
+  {
+    SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
+                                                             /*complexShapeFirst=*/false);
+    while ( smIt->more() )
+    {
+      sm = smIt->next();
+      TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();      
+      if ( shapeType == TopAbs_VERTEX || shapeType < TopAbs_SOLID )
+        // all other shapes depends on vertices so they are already cleaned
+        sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
+      // to recompute even if failed
+      sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    }
+  }
 }
 
 //=======================================================================
@@ -170,17 +345,47 @@ int SMESH_Mesh::UNVToMesh(const char* theFileName)
   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
   if(_isShapeToMesh)
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
-  _isShapeToMesh = true;
+  _isShapeToMesh = false;
   DriverUNV_R_SMDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetFile(theFileName);
   myReader.SetMeshId(-1);
   myReader.Perform();
   if(MYDEBUG){
-    MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
-    MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
-    MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
-    MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
+    MESSAGE("UNVToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
+    MESSAGE("UNVToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
+    MESSAGE("UNVToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
+    MESSAGE("UNVToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
+  }
+  SMDS_MeshGroup* aGroup = (SMDS_MeshGroup*) myReader.GetGroup();
+  if (aGroup != 0) {
+    TGroupNamesMap aGroupNames = myReader.GetGroupNamesMap();
+    //const TGroupIdMap& aGroupId = myReader.GetGroupIdMap();
+    aGroup->InitSubGroupsIterator();
+    while (aGroup->MoreSubGroups()) {
+      SMDS_MeshGroup* aSubGroup = (SMDS_MeshGroup*) aGroup->NextSubGroup();
+      string aName = aGroupNames[aSubGroup];
+      int aId;
+
+      SMESH_Group* aSMESHGroup = AddGroup( aSubGroup->GetType(), aName.c_str(), aId );
+      if ( aSMESHGroup ) {
+        if(MYDEBUG) MESSAGE("UNVToMesh - group added: "<<aName);      
+        SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aSMESHGroup->GetGroupDS() );
+        if ( aGroupDS ) {
+          aGroupDS->SetStoreName(aName.c_str());
+          aSubGroup->InitIterator();
+          const SMDS_MeshElement* aElement = 0;
+          while (aSubGroup->More()) {
+            aElement = aSubGroup->Next();
+            if (aElement) {
+              aGroupDS->SMDSGroup().Add(aElement);
+            }
+          }
+          if (aElement)
+            aGroupDS->SetType(aElement->GetType());
+        }
+      }
+    }
   }
   return 1;
 }
@@ -195,7 +400,7 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
   if(MYDEBUG) MESSAGE("MEDToMesh - theFileName = "<<theFileName<<", mesh name = "<<theMeshName);
   if(_isShapeToMesh)
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
-  _isShapeToMesh = true;
+  _isShapeToMesh = false;
   DriverMED_R_SMESHDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetMeshId(-1);
@@ -235,20 +440,20 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
 
 int SMESH_Mesh::STLToMesh(const char* theFileName)
 {
-  if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
+  if(MYDEBUG) MESSAGE("STLToMesh - theFileName = "<<theFileName);
   if(_isShapeToMesh)
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
-  _isShapeToMesh = true;
+  _isShapeToMesh = false;
   DriverSTL_R_SMDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetFile(theFileName);
   myReader.SetMeshId(-1);
   myReader.Perform();
   if(MYDEBUG){
-    MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
-    MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
-    MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
-    MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
+    MESSAGE("STLToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
+    MESSAGE("STLToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
+    MESSAGE("STLToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
+    MESSAGE("STLToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
   }
   return 1;
 }
@@ -267,28 +472,8 @@ SMESH_Hypothesis::Hypothesis_Status
   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
 
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
-  SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
-  if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) // group of sub-shapes and maybe of not sub-
-  {
-    MESSAGE("AddHypothesis() to complex submesh");
-    // return the worst but not fatal state of all group memebers
-    SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
-    aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
-    aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
-    for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
-    {
-      if ( !GetMeshDS()->ShapeToIndex( itS.Value() ))
-        continue; // not sub-shape
-      ret = AddHypothesis( itS.Value(), anHypId );
-      if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
-        aWorstNotFatal = ret;
-      if ( ret < aBestRet )
-        aBestRet = ret;
-    }
-    if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
-      return aBestRet;
-    return aWorstNotFatal;
-  }
+  if ( !subMesh || !subMesh->GetId())
+    return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
 
   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
@@ -319,21 +504,17 @@ SMESH_Hypothesis::Hypothesis_Status
 
   // shape 
 
-  int event;
-  if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
-    event = SMESH_subMesh::ADD_HYP;
-  else
-    event = SMESH_subMesh::ADD_ALGO;
+  bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
+  int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
+
   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
 
   // subShapes
   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
-      !subMesh->IsApplicableHypotesis( anHyp )) // is added on father
+      anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
   {
-    if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
-      event = SMESH_subMesh::ADD_FATHER_HYP;
-    else
-      event = SMESH_subMesh::ADD_FATHER_ALGO;
+    event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
+
     SMESH_Hypothesis::Hypothesis_Status ret2 =
       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
     if (ret2 > ret)
@@ -342,11 +523,11 @@ SMESH_Hypothesis::Hypothesis_Status
     // check concurent hypotheses on ansestors
     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
     {
-      const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn();
-      map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin();
-      for ( ; smIt != smMap.end(); smIt++ ) {
-        if ( smIt->second->IsApplicableHypotesis( anHyp )) {
-          ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() );
+      SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
+      while ( smIt->more() ) {
+        SMESH_subMesh* sm = smIt->next();
+        if ( sm->IsApplicableHypotesis( anHyp )) {
+          ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
           if (ret2 > ret) {
             ret = ret2;
             break;
@@ -374,29 +555,6 @@ SMESH_Hypothesis::Hypothesis_Status
   Unexpect aCatch(SalomeException);
   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
   
-  SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
-  SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
-  if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
-  {
-    // return the worst but not fatal state of all group memebers
-    SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
-    aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
-    aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
-    for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
-    {
-      if ( !GetMeshDS()->ShapeToIndex( itS.Value() ))
-        continue; // not sub-shape
-      ret = RemoveHypothesis( itS.Value(), anHypId );
-      if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
-        aWorstNotFatal = ret;
-      if ( ret < aBestRet )
-        aBestRet = ret;
-    }
-    if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
-      return aBestRet;
-    return aWorstNotFatal;
-  }
-
   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
@@ -404,14 +562,14 @@ SMESH_Hypothesis::Hypothesis_Status
   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
   int hypType = anHyp->GetType();
   if(MYDEBUG) SCRUTE(hypType);
-  int event;
   
   // shape 
   
-  if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
-    event = SMESH_subMesh::REMOVE_HYP;
-  else
-    event = SMESH_subMesh::REMOVE_ALGO;
+  bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
+  int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
+
+  SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
+
   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
 
   // there may appear concurrent hyps that were covered by the removed hyp
@@ -422,12 +580,10 @@ SMESH_Hypothesis::Hypothesis_Status
 
   // subShapes
   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
-      !subMesh->IsApplicableHypotesis( anHyp )) // is removed from father
+      anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is removed from father
   {
-    if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
-      event = SMESH_subMesh::REMOVE_FATHER_HYP;
-    else
-      event = SMESH_subMesh::REMOVE_FATHER_ALGO;
+    event = isAlgo ? SMESH_subMesh::REMOVE_FATHER_ALGO : SMESH_subMesh::REMOVE_FATHER_HYP;
+
     SMESH_Hypothesis::Hypothesis_Status ret2 =
       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
     if (ret2 > ret) // more severe
@@ -436,11 +592,11 @@ SMESH_Hypothesis::Hypothesis_Status
     // check concurent hypotheses on ansestors
     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) )
     {
-      const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn();
-      map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin();
-      for ( ; smIt != smMap.end(); smIt++ ) {
-        if ( smIt->second->IsApplicableHypotesis( anHyp )) {
-          ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() );
+      SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
+      while ( smIt->more() ) {
+        SMESH_subMesh* sm = smIt->next();
+        if ( sm->IsApplicableHypotesis( anHyp )) {
+          ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
           if (ret2 > ret) {
             ret = ret2;
             break;
@@ -461,17 +617,6 @@ SMESH_Hypothesis::Hypothesis_Status
  */
 //=============================================================================
 
-SMESHDS_Mesh * SMESH_Mesh::GetMeshDS()
-{
-  return _myMeshDS;
-}
-
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
-
 const list<const SMESHDS_Hypothesis*>&
 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
@@ -481,84 +626,127 @@ SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
 }
 
 //=======================================================================
-//function : GetHypothesis
-//purpose  : 
+/*!
+ * \brief Return the hypothesis assigned to the shape
+ *  \param aSubShape    - the shape to check
+ *  \param aFilter      - the hypothesis filter
+ *  \param andAncestors - flag to check hypos assigned to ancestors of the shape
+ *  \param assignedTo   - to return the shape the found hypo is assigned to
+ *  \retval SMESH_Hypothesis* - the first hypo passed through aFilter
+ */
 //=======================================================================
 
 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
                                                    const SMESH_HypoFilter& aFilter,
-                                                   const bool              andAncestors) const
+                                                   const bool              andAncestors,
+                                                   TopoDS_Shape*           assignedTo) const
 {
   {
     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
     list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
     for ( ; hyp != hypList.end(); hyp++ ) {
-      const SMESH_Hypothesis * h = static_cast<const SMESH_Hypothesis*>( *hyp );
-      if ( aFilter.IsOk( h, aSubShape))
+      const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
+      if ( aFilter.IsOk( h, aSubShape)) {
+        if ( assignedTo ) *assignedTo = aSubShape;
         return h;
+      }
     }
   }
   if ( andAncestors )
   {
-    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
-    for (; it.More(); it.Next() )
+    // user sorted submeshes of ancestors, according to stored submesh priority
+    const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
+    for ( ; smIt != smList.end(); smIt++ )
     {
-      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
+      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
       for ( ; hyp != hypList.end(); hyp++ ) {
-        const SMESH_Hypothesis * h = static_cast<const SMESH_Hypothesis*>( *hyp );
-        if (aFilter.IsOk( h, it.Value() ))
+        const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
+        if (aFilter.IsOk( h, curSh )) {
+          if ( assignedTo ) *assignedTo = curSh;
           return h;
+        }
       }
     }
   }
   return 0;
 }
 
-//=======================================================================
-//function : GetHypotheses
-//purpose  : 
-//=======================================================================
+//================================================================================
+/*!
+ * \brief Return hypothesis assigned to the shape
+  * \param aSubShape - the shape to check
+  * \param aFilter - the hypothesis filter
+  * \param aHypList - the list of the found hypotheses
+  * \param andAncestors - flag to check hypos assigned to ancestors of the shape
+  * \retval int - number of unique hypos in aHypList
+ */
+//================================================================================
 
-bool SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
-                               const SMESH_HypoFilter&             aFilter,
-                               list <const SMESHDS_Hypothesis * >& aHypList,
-                               const bool                          andAncestors) const
+int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
+                              const SMESH_HypoFilter&             aFilter,
+                              list <const SMESHDS_Hypothesis * >& aHypList,
+                              const bool                          andAncestors) const
 {
-  int nbHyp = 0;
+  set<string> hypTypes; // to exclude same type hypos from the result list
+  int nbHyps = 0;
+
+  // only one main hypothesis is allowed
+  bool mainHypFound = false;
+
+  // fill in hypTypes
+  list<const SMESHDS_Hypothesis*>::const_iterator hyp;
+  for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
+    if ( hypTypes.insert( (*hyp)->GetName() ).second )
+      nbHyps++;
+    if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+      mainHypFound = true;
+  }
+
+  // get hypos from aSubShape
   {
     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
-    list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
-    for ( ; hyp != hypList.end(); hyp++ )
-      if ( aFilter.IsOk (static_cast<const SMESH_Hypothesis*>( *hyp ), aSubShape)) {
+    for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
+      if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) &&
+           ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
+           hypTypes.insert( (*hyp)->GetName() ).second )
+      {
         aHypList.push_back( *hyp );
-        nbHyp++;
+        nbHyps++;
+        if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+          mainHypFound = true;
       }
   }
-  // get hypos from shape of one type only: if any hypo is found on edge, do
-  // not look up on faces
-  if ( !nbHyp && andAncestors )
+
+  // get hypos from ancestors of aSubShape
+  if ( andAncestors )
   {
     TopTools_MapOfShape map;
-    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
-    int shapeType = it.More() ? it.Value().ShapeType() : TopAbs_SHAPE;
-    for (; it.More(); it.Next() )
+
+    // user sorted submeshes of ancestors, according to stored submesh priority
+    const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
+    for ( ; smIt != smList.end(); smIt++ )
     {
-      if ( nbHyp && shapeType != it.Value().ShapeType() )
-        break;
-      shapeType = it.Value().ShapeType();
-      if ( !map.Add( it.Value() ))
+      const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
+     if ( !map.Add( curSh ))
         continue;
-      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
-      list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
-      for ( ; hyp != hypList.end(); hyp++ )
-        if (aFilter.IsOk( static_cast<const SMESH_Hypothesis*>( *hyp ), it.Value() )) {
-        aHypList.push_back( *hyp );
-        nbHyp++;
-      }
+      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
+      for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
+        if (aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh ) &&
+            ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
+            hypTypes.insert( (*hyp)->GetName() ).second )
+        {
+          aHypList.push_back( *hyp );
+          nbHyps++;
+          if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+            mainHypFound = true;
+        }
     }
   }
-  return nbHyp;
+  return nbHyps;
 }
 
 //=============================================================================
@@ -586,29 +774,6 @@ void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
   _myMeshDS->GetScript()->Clear();
 }
 
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
-
-int SMESH_Mesh::GetId()
-{
-  if(MYDEBUG) MESSAGE("SMESH_Mesh::GetId");
-  return _id;
-}
-
-//=============================================================================
-/*!
- * 
- */
-//=============================================================================
-
-SMESH_Gen *SMESH_Mesh::GetGen()
-{
-  return _gen;
-}
-
 //=============================================================================
 /*!
  * Get or Create the SMESH_subMesh object implementation
@@ -616,28 +781,38 @@ SMESH_Gen *SMESH_Mesh::GetGen()
 //=============================================================================
 
 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
-throw(SALOME_Exception)
+  throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
   SMESH_subMesh *aSubMesh;
   int index = _myMeshDS->ShapeToIndex(aSubShape);
-  
+
   // for submeshes on GEOM Group
-  if ( !index && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
+  if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
     TopoDS_Iterator it( aSubShape );
     if ( it.More() )
+    {
       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
-  }
+      if ( index > _nbSubShapes ) _nbSubShapes = index; // not to create sm for this group again
 
-  if (_mapSubMesh.find(index) != _mapSubMesh.end())
-    {
-      aSubMesh = _mapSubMesh[index];
+      // fill map of Ancestors
+      fillAncestorsMap(aSubShape);
     }
+  }
+//   if ( !index )
+//     return NULL; // neither sub-shape nor a group
+
+  map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
+  if ( i_sm != _mapSubMesh.end())
+  {
+    aSubMesh = i_sm->second;
+  }
   else
-    {
-      aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
-      _mapSubMesh[index] = aSubMesh;
-    }
+  {
+    aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
+    _mapSubMesh[index] = aSubMesh;
+    ClearMeshOrder();
+  }
   return aSubMesh;
 }
 
@@ -648,24 +823,20 @@ throw(SALOME_Exception)
  */
 //=============================================================================
 
-SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
-throw(SALOME_Exception)
+SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
+  throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  bool isFound = false;
   SMESH_subMesh *aSubMesh = NULL;
   
   int index = _myMeshDS->ShapeToIndex(aSubShape);
-  if (_mapSubMesh.find(index) != _mapSubMesh.end())
-    {
-      aSubMesh = _mapSubMesh[index];
-      isFound = true;
-    }
-  if (!isFound)
-    aSubMesh = NULL;
+
+  map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
+  if ( i_sm != _mapSubMesh.end())
+    aSubMesh = i_sm->second;
+
   return aSubMesh;
 }
-
 //=============================================================================
 /*!
  * Get the SMESH_subMesh object implementation. Dont create it, return null
@@ -673,32 +844,68 @@ throw(SALOME_Exception)
  */
 //=============================================================================
 
-SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID)
+SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
 throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
   
-  map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(aShapeID);
+  map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(aShapeID);
   if (i_sm == _mapSubMesh.end())
     return NULL;
   return i_sm->second;
 }
+//================================================================================
+/*!
+ * \brief Return submeshes of groups containing the given subshape
+ */
+//================================================================================
 
+list<SMESH_subMesh*>
+SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
+  throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  list<SMESH_subMesh*> found;
+
+  SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
+  if ( !subMesh )
+    return found;
+
+  // submeshes of groups have max IDs, so search from the map end
+  map<int, SMESH_subMesh *>::const_reverse_iterator i_sm;
+  for ( i_sm = _mapSubMesh.rbegin(); i_sm != _mapSubMesh.rend(); ++i_sm) {
+    SMESHDS_SubMesh * ds = i_sm->second->GetSubMeshDS();
+    if ( ds && ds->IsComplexSubmesh() ) {
+      TopExp_Explorer exp( i_sm->second->GetSubShape(), aSubShape.ShapeType() );
+      for ( ; exp.More(); exp.Next() ) {
+        if ( aSubShape.IsSame( exp.Current() )) {
+          found.push_back( i_sm->second );
+          break;
+        }
+      }
+    } else {
+      break;
+    }
+  }
+  return found;
+}
 //=======================================================================
 //function : IsUsedHypothesis
 //purpose  : Return True if anHyp is used to mesh aSubShape
 //=======================================================================
 
 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
-                                  const TopoDS_Shape & aSubShape)
+                                  const SMESH_subMesh* aSubMesh)
 {
   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
-  // check if anHyp is applicable to aSubShape
-  SMESH_subMesh * subMesh = GetSubMeshContaining( aSubShape );
-  if ( !subMesh || !subMesh->IsApplicableHypotesis( hyp ))
+
+  // check if anHyp can be used to mesh aSubMesh
+  if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
     return false;
 
-  SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape);
+  const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
+
+  SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
 
   // algorithm
   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
@@ -708,17 +915,19 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
   if (algo)
   {
     // look trough hypotheses used by algo
-    const list <const SMESHDS_Hypothesis * >&usedHyps =
-      algo->GetUsedHypothesis(*this, aSubShape);
-    return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
+    SMESH_HypoFilter hypoKind;
+    if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
+      list <const SMESHDS_Hypothesis * > usedHyps;
+      if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
+        return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
+    }
   }
 
   // look through all assigned hypotheses
-  SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
-  return GetHypothesis( aSubShape, filter, true );
+  //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
+  return false; //GetHypothesis( aSubShape, filter, true );
 }
 
-
 //=============================================================================
 /*!
  *
@@ -726,35 +935,123 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
 //=============================================================================
 
 const list < SMESH_subMesh * >&
-       SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
-throw(SALOME_Exception)
+SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
+  throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
+  map < int, SMESH_subMesh * >::iterator itsm;
+  _subMeshesUsingHypothesisList.clear();
+  for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
+  {
+    SMESH_subMesh *aSubMesh = (*itsm).second;
+    if ( IsUsedHypothesis ( anHyp, aSubMesh ))
+      _subMeshesUsingHypothesisList.push_back(aSubMesh);
+  }
+  return _subMeshesUsingHypothesisList;
+}
+
+//=======================================================================
+//function : NotifySubMeshesHypothesisModification
+//purpose  : Say all submeshes using theChangedHyp that it has been modified
+//=======================================================================
+
+void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
 {
   Unexpect aCatch(SalomeException);
-       if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
-       map < int, SMESH_subMesh * >::iterator itsm;
-       _subMeshesUsingHypothesisList.clear();
-       for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
-       {
-               SMESH_subMesh *aSubMesh = (*itsm).second;
-               if ( IsUsedHypothesis ( anHyp, aSubMesh->GetSubShape() ))
-                       _subMeshesUsingHypothesisList.push_back(aSubMesh);
-       }
-       return _subMeshesUsingHypothesisList;
+
+  const SMESH_Algo *foundAlgo = 0;
+  SMESH_HypoFilter algoKind, compatibleHypoKind;
+  list <const SMESHDS_Hypothesis * > usedHyps;
+
+
+  map < int, SMESH_subMesh * >::iterator itsm;
+  for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
+  {
+    SMESH_subMesh *aSubMesh = (*itsm).second;
+    if ( aSubMesh->IsApplicableHypotesis( hyp ))
+    {
+      const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
+
+      if ( !foundAlgo ) // init filter for algo search
+        algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
+      
+      const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
+        ( GetHypothesis( aSubShape, algoKind, true ));
+
+      if ( algo )
+      {
+        bool sameAlgo = ( algo == foundAlgo );
+        if ( !sameAlgo && foundAlgo )
+          sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
+
+        if ( !sameAlgo ) { // init filter for used hypos search
+          if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
+            continue; // algo does not use any hypothesis
+          foundAlgo = algo;
+        }
+
+        // check if hyp is used by algo
+        usedHyps.clear();
+        if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
+             find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
+        {
+          aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
+                                    const_cast< SMESH_Hypothesis*>( hyp ));
+        }
+      }
+    }
+  }
 }
 
 //=============================================================================
 /*!
- *
+ *  Auto color functionality
+ */
+//=============================================================================
+void SMESH_Mesh::SetAutoColor(bool theAutoColor) throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  _isAutoColor = theAutoColor;
+}
+
+bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  return _isAutoColor;
+}
+
+//=============================================================================
+/*! Export* methods.
+ *  To store mesh contents on disk in different formats.
  */
 //=============================================================================
 
+bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
+{
+  //set<string> aGroupNames; // Corrected for Mantis issue 0020028
+  map< SMDSAbs_ElementType, set<string> > aGroupNames;
+  for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
+  {
+    SMESH_Group* aGroup = it->second;
+    SMDSAbs_ElementType aType = aGroup->GetGroupDS()->GetType();
+    string aGroupName = aGroup->GetName();
+    aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
+    if (!aGroupNames[aType].insert(aGroupName).second)
+      return true;
+  }
+
+  return false;
+}
+
 void SMESH_Mesh::ExportMED(const char *file, 
-                          const char* theMeshName, 
-                          bool theAutoGroups,
-                          int theVersion) 
+                           const char* theMeshName, 
+                           bool theAutoGroups,
+                           int theVersion) 
   throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
+
   DriverMED_W_SMESHDS_Mesh myWriter;
   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
   myWriter.SetMesh    ( _myMeshDS   );
@@ -772,15 +1069,30 @@ void SMESH_Mesh::ExportMED(const char *file,
     myWriter.AddGroupOfVolumes();
   }
 
+  // Pass groups to writer. Provide unique group names.
+  //set<string> aGroupNames; // Corrected for Mantis issue 0020028
+  map< SMDSAbs_ElementType, set<string> > aGroupNames;
+  char aString [256];
+  int maxNbIter = 10000; // to guarantee cycle finish
   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
     SMESH_Group*       aGroup   = it->second;
     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
     if ( aGroupDS ) {
-      aGroupDS->SetStoreName( aGroup->GetName() );
+      SMDSAbs_ElementType aType = aGroupDS->GetType();
+      string aGroupName0 = aGroup->GetName();
+      aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
+      string aGroupName = aGroupName0;
+      for (int i = 1; !aGroupNames[aType].insert(aGroupName).second && i < maxNbIter; i++) {
+        sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
+        aGroupName = aString;
+        aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
+      }
+      aGroupDS->SetStoreName( aGroupName.c_str() );
       myWriter.AddGroup( aGroupDS );
     }
   }
 
+  // Perform export
   myWriter.Perform();
 }
 
@@ -801,6 +1113,17 @@ void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
   myWriter.SetFile(string(file));
   myWriter.SetMesh(_myMeshDS);
   myWriter.SetMeshId(_idDoc);
+  //  myWriter.SetGroups(_mapGroup);
+
+  for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
+    SMESH_Group*       aGroup   = it->second;
+    SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
+    if ( aGroupDS ) {
+      string aGroupName = aGroup->GetName();
+      aGroupDS->SetStoreName( aGroupName.c_str() );
+      myWriter.AddGroup( aGroupDS );
+    }
+  }
   myWriter.Perform();
 }
 
@@ -815,170 +1138,168 @@ void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Ex
   myWriter.Perform();
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  
+ * \brief Return number of nodes in the mesh
  */
-//=============================================================================
+//================================================================================
+
 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
   return _myMeshDS->NbNodes();
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  
+ * \brief  Return number of edges of given order in the mesh
  */
-//=============================================================================
-int SMESH_Mesh::NbEdges() throw(SALOME_Exception)
+//================================================================================
+
+int SMESH_Mesh::Nb0DElements() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  return _myMeshDS->NbEdges();
+  return _myMeshDS->GetMeshInfo().Nb0DElements();
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  
+ * \brief  Return number of edges of given order in the mesh
  */
-//=============================================================================
-int SMESH_Mesh::NbFaces() throw(SALOME_Exception)
+//================================================================================
+
+int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  return _myMeshDS->NbFaces();
+  return _myMeshDS->GetMeshInfo().NbEdges(order);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Return the number of 3 nodes faces in the mesh. This method run in O(n)
-///////////////////////////////////////////////////////////////////////////////
-int SMESH_Mesh::NbTriangles() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief Return number of faces of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  
-  SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
-  //while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++;
-  const SMDS_MeshFace * curFace;
-  while (itFaces->more()) {
-    curFace = itFaces->next();
-    if (!curFace->IsPoly() && curFace->NbNodes() == 3) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbFaces(order);
+}
+
+//================================================================================
+/*!
+ * \brief Return the number of faces in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  return _myMeshDS->GetMeshInfo().NbTriangles(order);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Return the number of 4 nodes faces in the mesh. This method run in O(n)
-///////////////////////////////////////////////////////////////////////////////
-int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief Return the number nodes faces in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  
-  SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
-  //while(itFaces->more()) if(itFaces->next()->NbNodes()==4) Nb++;
-  const SMDS_MeshFace * curFace;
-  while (itFaces->more()) {
-    curFace = itFaces->next();
-    if (!curFace->IsPoly() && curFace->NbNodes() == 4) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Return the number of polygonal faces in the mesh. This method run in O(n)
-///////////////////////////////////////////////////////////////////////////////
+//================================================================================
+/*!
+ * \brief Return the number of polygonal faces in the mesh
+ */
+//================================================================================
+
 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_FaceIteratorPtr itFaces = _myMeshDS->facesIterator();
-  while (itFaces->more())
-    if (itFaces->next()->IsPoly()) Nb++;
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbPolygons();
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  
+ * \brief Return number of volumes of given order in the mesh
  */
-//=============================================================================
-int SMESH_Mesh::NbVolumes() throw(SALOME_Exception)
+//================================================================================
+
+int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  return _myMeshDS->NbVolumes();
+  return _myMeshDS->GetMeshInfo().NbVolumes(order);
 }
 
-int SMESH_Mesh::NbTetras() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief  Return number of tetrahedrons of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++;
-  const SMDS_MeshVolume * curVolume;
-  while (itVolumes->more()) {
-    curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 4) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbTetras(order);
 }
 
-int SMESH_Mesh::NbHexas() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief  Return number of hexahedrons of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++;
-  const SMDS_MeshVolume * curVolume;
-  while (itVolumes->more()) {
-    curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 8) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbHexas(order);
 }
 
-int SMESH_Mesh::NbPyramids() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief  Return number of pyramids of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++;
-  const SMDS_MeshVolume * curVolume;
-  while (itVolumes->more()) {
-    curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 5) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbPyramids(order);
 }
 
-int SMESH_Mesh::NbPrisms() throw(SALOME_Exception)
+//================================================================================
+/*!
+ * \brief  Return number of prisms (penthahedrons) of given order in the mesh
+ */
+//================================================================================
+
+int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  //while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++;
-  const SMDS_MeshVolume * curVolume;
-  while (itVolumes->more()) {
-    curVolume = itVolumes->next();
-    if (!curVolume->IsPoly() && curVolume->NbNodes() == 6) Nb++;
-  }
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbPrisms(order);
 }
 
+//================================================================================
+/*!
+ * \brief  Return number of polyhedrons in the mesh
+ */
+//================================================================================
+
 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  int Nb = 0;
-  SMDS_VolumeIteratorPtr itVolumes = _myMeshDS->volumesIterator();
-  while (itVolumes->more())
-    if (itVolumes->next()->IsPoly()) Nb++;
-  return Nb;
+  return _myMeshDS->GetMeshInfo().NbPolyhedrons();
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  
+ * \brief  Return number of submeshes in the mesh
  */
-//=============================================================================
+//================================================================================
+
 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
@@ -994,7 +1315,7 @@ bool SMESH_Mesh::IsNotConformAllowed() const
 {
   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
 
-  SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
+  static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
 }
 
@@ -1016,7 +1337,7 @@ bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
 
 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
                                    const char*               theName,
-                                  int&                      theId,
+                                   int&                      theId,
                                    const TopoDS_Shape&       theShape)
 {
   if (_mapGroup.find(_groupId) != _mapGroup.end())
@@ -1028,9 +1349,21 @@ SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
   return aGroup;
 }
 
+//================================================================================
+/*!
+ * \brief Return iterator on all existing groups
+ */
+//================================================================================
+
+SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
+{
+  typedef map <int, SMESH_Group *> TMap;
+  return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
+}
+
 //=============================================================================
 /*!
- *  
+ * \brief Return a group by ID
  */
 //=============================================================================
 
@@ -1044,11 +1377,11 @@ SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
 
 //=============================================================================
 /*!
- *  
+ * \brief Return IDs of all groups
  */
 //=============================================================================
 
-list<int> SMESH_Mesh::GetGroupIds()
+list<int> SMESH_Mesh::GetGroupIds() const
 {
   list<int> anIds;
   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
@@ -1073,358 +1406,260 @@ void SMESH_Mesh::RemoveGroup (const int theGroupID)
   _mapGroup.erase (theGroupID);
 }
 
-//=============================================================================
-/*!
- *  IsLocal1DHypothesis
- *  Returns a local 1D hypothesis used for theEdge
- */
-//=============================================================================
-const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
+//=======================================================================
+//function : GetAncestors
+//purpose  : return list of ancestors of theSubShape in the order
+//           that lower dimention shapes come first.
+//=======================================================================
+
+const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
 {
-  SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
-  hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() ));
+  if ( _mapAncestors.Contains( theS ) )
+    return _mapAncestors.FindFromKey( theS );
 
-  return GetHypothesis( theEdge, hypo, true );
+  static TopTools_ListOfShape emptyList;
+  return emptyList;
 }
 
-//=============================================================================
-/*!
- *  IsPropagationHypothesis
- */
-//=============================================================================
-bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge)
+//=======================================================================
+//function : Dump
+//purpose  : dumps contents of mesh to stream [ debug purposes ]
+//=======================================================================
+
+ostream& SMESH_Mesh::Dump(ostream& save)
 {
-  return _mapPropagationChains.Contains(theEdge);
+  int clause = 0;
+  save << "========================== Dump contents of mesh ==========================" << endl << endl;
+  save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
+  save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
+  save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
+  save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
+  save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
+  save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
+  for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
+  {
+    string orderStr = isQuadratic ? "quadratic" : "linear";
+    SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
+
+    save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
+    save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
+    if ( NbFaces(order) > 0 ) {
+      int nb3 = NbTriangles(order);
+      int nb4 = NbQuadrangles(order);
+      save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
+      save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
+      if ( nb3 + nb4 !=  NbFaces(order) ) {
+        map<int,int> myFaceMap;
+        SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
+        while( itFaces->more( ) ) {
+          int nbNodes = itFaces->next()->NbNodes();
+          if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
+            myFaceMap[ nbNodes ] = 0;
+          myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
+        }
+        save << clause << ".3) Faces in detail: " << endl;
+        map <int,int>::iterator itF;
+        for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
+          save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
+      }
+    }
+    save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
+    if ( NbVolumes(order) > 0 ) {
+      int nb8 = NbHexas(order);
+      int nb4 = NbTetras(order);
+      int nb5 = NbPyramids(order);
+      int nb6 = NbPrisms(order);
+      save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
+      save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
+      save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
+      save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
+      if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
+        map<int,int> myVolumesMap;
+        SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
+        while( itVolumes->more( ) ) {
+          int nbNodes = itVolumes->next()->NbNodes();
+          if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
+            myVolumesMap[ nbNodes ] = 0;
+          myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
+        }
+        save << clause << ".5) Volumes in detail: " << endl;
+        map <int,int>::iterator itV;
+        for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
+          save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
+      }
+    }
+    save << endl;
+  }
+  save << "===========================================================================" << endl;
+  return save;
+}
+
+//=======================================================================
+//function : GetElementType
+//purpose  : Returns type of mesh element with certain id
+//=======================================================================
+
+SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
+{
+  return _myMeshDS->GetElementType( id, iselem );
 }
 
 //=============================================================================
 /*!
- *  IsPropagatedHypothesis
+ *  \brief Convert group on geometry into standalone group
  */
 //=============================================================================
-bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge,
-                                         TopoDS_Shape&       theMainEdge)
-{
-  int nbChains = _mapPropagationChains.Extent();
-  for (int i = 1; i <= nbChains; i++) {
-    //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
-    const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
-    if (aChain.Contains(theEdge)) {
-      theMainEdge = _mapPropagationChains.FindKey(i);
-      return true;
-    }
-  }
 
-  return false;
+SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
+{
+  SMESH_Group* aGroup = 0;
+  map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
+  if ( itg == _mapGroup.end() )
+    return aGroup;
+
+  SMESH_Group* anOldGrp = (*itg).second;
+  SMESHDS_GroupBase* anOldGrpDS = anOldGrp->GetGroupDS();
+  if ( !anOldGrp || !anOldGrpDS )
+    return aGroup;
+
+  // create new standalone group
+  aGroup = new SMESH_Group (theGroupID, this, anOldGrpDS->GetType(), anOldGrp->GetName() );
+  _mapGroup[theGroupID] = aGroup;
+
+  SMESHDS_Group* aNewGrpDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
+  GetMeshDS()->RemoveGroup( anOldGrpDS );
+  GetMeshDS()->AddGroup( aNewGrpDS );
+
+  // add elements (or nodes) into new created group
+  SMDS_ElemIteratorPtr anItr = anOldGrpDS->GetElements();
+  while ( anItr->more() )
+    aNewGrpDS->Add( (anItr->next())->GetID() );
+
+  // remove old group
+  delete anOldGrp;
+
+  return aGroup;
 }
+
 //=============================================================================
 /*!
- *  IsReversedInChain
+ *  \brief remove submesh order  from Mesh
  */
 //=============================================================================
 
-bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
-                                    const TopoDS_Shape& theMainEdge)
+void SMESH_Mesh::ClearMeshOrder()
 {
-  if ( !theMainEdge.IsNull() && !theEdge.IsNull() &&
-      _mapPropagationChains.Contains( theMainEdge ))
-  {
-    const SMESH_IndexedMapOfShape& aChain =
-      _mapPropagationChains.FindFromKey( theMainEdge );
-    int index = aChain.FindIndex( theEdge );
-    if ( index )
-      return aChain(index).Orientation() == TopAbs_REVERSED;
-  }
-  return false;
+  _mySubMeshOrder.clear();
 }
 
 //=============================================================================
 /*!
- *  CleanMeshOnPropagationChain
+ *  \brief remove submesh order  from Mesh
  */
 //=============================================================================
-void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge)
-{
-  const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge);
-  int i, nbEdges = aChain.Extent();
-  for (i = 1; i <= nbEdges; i++) {
-    TopoDS_Shape anEdge = aChain.FindKey(i);
-    SMESH_subMesh *subMesh = GetSubMesh(anEdge);
-    SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
-    if (subMeshDS && subMeshDS->NbElements() > 0) {
-      subMesh->ComputeStateEngine(SMESH_subMesh::CLEANDEP);
-    }
-  }
+
+void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
+{
+  _mySubMeshOrder = theOrder;
 }
 
 //=============================================================================
 /*!
- *  RebuildPropagationChains
- *  Rebuild all existing propagation chains.
- *  Have to be used, if 1D hypothesis have been assigned/removed to/from any edge
+ *  \brief return submesh order if any
  */
 //=============================================================================
-bool SMESH_Mesh::RebuildPropagationChains()
-{
-  bool ret = true;
-
-  // Clean all chains, because they can be not up-to-date
-  int i, nbChains = _mapPropagationChains.Extent();
-  for (i = 1; i <= nbChains; i++) {
-    TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
-    CleanMeshOnPropagationChain(aMainEdge);
-    _mapPropagationChains.ChangeFromIndex(i).Clear();
-  }
 
-  // Build all chains
-  for (i = 1; i <= nbChains; i++) {
-    TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
-    if (!BuildPropagationChain(aMainEdge))
-      ret = false;
-    CleanMeshOnPropagationChain(aMainEdge);
-  }
-
-  return ret;
+const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
+{
+  return _mySubMeshOrder;
 }
 
 //=============================================================================
 /*!
- *  RemovePropagationChain
- *  Have to be used, if Propagation hypothesis is removed from <theMainEdge>
+ *  \brief fillAncestorsMap
  */
 //=============================================================================
-bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge)
-{
-  if (!_mapPropagationChains.Contains(theMainEdge))
-    return false;
-
-  // Clean mesh elements and nodes, built on the chain
-  CleanMeshOnPropagationChain(theMainEdge);
-
-  // Clean the chain
-  _mapPropagationChains.ChangeFromKey(theMainEdge).Clear();
-
-  // Remove the chain from the map
-  int i = _mapPropagationChains.FindIndex(theMainEdge);
-  if ( i == _mapPropagationChains.Extent() )
-    _mapPropagationChains.RemoveLast();
-  else {
-    TopoDS_Vertex anEmptyShape;
-    BRep_Builder BB;
-    BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1);
-    SMESH_IndexedMapOfShape anEmptyMap;
-    _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap);
-  }
 
-  return true;
+void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
+{
+  // fill _mapAncestors
+  int desType, ancType;
+  for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
+    for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
+      TopExp::MapShapesAndAncestors ( theShape,
+                                      (TopAbs_ShapeEnum) desType,
+                                      (TopAbs_ShapeEnum) ancType,
+                                      _mapAncestors );
 }
 
 //=============================================================================
 /*!
- *  BuildPropagationChain
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
  */
 //=============================================================================
-bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
-{
-  if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
-
-  // Add new chain, if there is no
-  if (!_mapPropagationChains.Contains(theMainEdge)) {
-    SMESH_IndexedMapOfShape aNewChain;
-    _mapPropagationChains.Add(theMainEdge, aNewChain);
-  }
 
-  // Check presence of 1D hypothesis to be propagated
-  const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge);
-  if (!aMainHyp) {
-    MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign.");
+bool SMESH_Mesh::SortByMeshOrder(list<SMESH_subMesh*>& theListToSort) const
+{
+  if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
     return true;
+  
+  bool res = false;
+  list<SMESH_subMesh*> onlyOrderedList;
+  // collect all ordered submeshes in one list as pointers
+  // and get their positions within theListToSort
+  typedef list<SMESH_subMesh*>::iterator TPosInList;
+  map< int, TPosInList > sortedPos;
+  TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
+  TListOfListOfInt::const_iterator listIddIt = _mySubMeshOrder.begin();
+  for( ; listIddIt != _mySubMeshOrder.end(); listIddIt++) {
+    const TListOfInt& listOfId = *listIddIt;
+    TListOfInt::const_iterator idIt = listOfId.begin();
+    for ( ; idIt != listOfId.end(); idIt++ ) {
+      if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt )) {
+        TPosInList smPos = find( smBeg, smEnd, sm );
+        if ( smPos != smEnd ) {
+          onlyOrderedList.push_back( sm );
+          sortedPos[ distance( smBeg, smPos )] = smPos;
+        }
+      }
+    }
   }
+  if (onlyOrderedList.size() < 2)
+    return res;
+  res = true;
 
-  // Edges, on which the 1D hypothesis will be propagated from <theMainEdge>
-  SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
-  if (aChain.Extent() > 0) {
-    CleanMeshOnPropagationChain(theMainEdge);
-    aChain.Clear();
-  }
+  list<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+  list<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
 
-  // At first put <theMainEdge> in the chain
-  aChain.Add(theMainEdge);
-
-  // List of edges, added to chain on the previous cycle pass
-  TopTools_ListOfShape listPrevEdges;
-  listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD ));
-
-//   5____4____3____4____5____6
-//   |    |    |    |    |    |
-//   |    |    |    |    |    |
-//   4____3____2____3____4____5
-//   |    |    |    |    |    |      Number in the each knot of
-//   |    |    |    |    |    |      grid indicates cycle pass,
-//   3____2____1____2____3____4      on which corresponding edge
-//   |    |    |    |    |    |      (perpendicular to the plane
-//   |    |    |    |    |    |      of view) will be found.
-//   2____1____0____1____2____3
-//   |    |    |    |    |    |
-//   |    |    |    |    |    |
-//   3____2____1____2____3____4
-
-  // Collect all edges pass by pass
-  while (listPrevEdges.Extent() > 0) {
-    // List of edges, added to chain on this cycle pass
-    TopTools_ListOfShape listCurEdges;
-
-    // Find the next portion of edges
-    TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
-    for (; itE.More(); itE.Next()) {
-      TopoDS_Shape anE = itE.Value();
-
-      // Iterate on faces, having edge <anE>
-      TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE));
-      for (; itA.More(); itA.Next()) {
-        TopoDS_Shape aW = itA.Value();
-
-        // There are objects of different type among the ancestors of edge
-        if (aW.ShapeType() == TopAbs_WIRE) {
-          TopoDS_Shape anOppE;
-
-          BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
-          Standard_Integer nb = 1, found = 0;
-          TopTools_Array1OfShape anEdges (1,4);
-          for (; aWE.More(); aWE.Next(), nb++) {
-            if (nb > 4) {
-              found = 0;
-              break;
-            }
-            anEdges(nb) = aWE.Current();
-            if (!_mapAncestors.Contains(anEdges(nb))) {
-              MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!");
-              break;
-            }
-            if (anEdges(nb).IsSame(anE)) found = nb;
-          }
-
-          if (nb == 5 && found > 0) {
-            // Quadrangle face found, get an opposite edge
-            Standard_Integer opp = found + 2;
-            if (opp > 4) opp -= 4;
-            anOppE = anEdges(opp);
-
-            // add anOppE to aChain if ...
-            if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
-              if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE
-                TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE
-                if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge))
-                {
-                  // Add found edge to the chain oriented so that to
-                  // have it co-directed with a forward MainEdge
-                  TopAbs_Orientation ori = anE.Orientation();
-                  if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
-                    ori = TopAbs::Reverse( ori );
-                  anOppE.Orientation( ori );
-                  aChain.Add(anOppE);
-                  listCurEdges.Append(anOppE);
-                }
-                else {
-                  // Collision!
-                  MESSAGE("Error: Collision between propagated hypotheses");
-                  CleanMeshOnPropagationChain(theMainEdge);
-                  aChain.Clear();
-                  return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) );
-                }
-              }
-            }
-          } // if (nb == 5 && found > 0)
-        } // if (aF.ShapeType() == TopAbs_WIRE)
-      } // for (; itF.More(); itF.Next())
-    } // for (; itE.More(); itE.Next())
-
-    listPrevEdges = listCurEdges;
-  } // while (listPrevEdges.Extent() > 0)
+  // iterates on ordered submeshes and insert them in detected positions
+  map< int, TPosInList >::iterator i_pos = sortedPos.begin();
+  for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
+    *(i_pos->second) = *onlyBIt;
 
-  CleanMeshOnPropagationChain(theMainEdge);
-  return true;
+  return res;
 }
 
-//=======================================================================
-//function : GetAncestors
-//purpose  : return list of ancestors of theSubShape in the order
-//           that lower dimention shapes come first.
-//=======================================================================
+//=============================================================================
+/*!
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
+ */
+//=============================================================================
 
-const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
+list<SMESH_subMesh*> SMESH_Mesh::getAncestorsSubMeshes
+  (const TopoDS_Shape& theSubShape) const
 {
-  if ( _mapAncestors.Contains( theS ) )
-    return _mapAncestors.FindFromKey( theS );
+  list<SMESH_subMesh*> listOfSubMesh;
+  TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
+  for (; it.More(); it.Next() )
+    if ( SMESH_subMesh* sm = GetSubMeshContaining( it.Value() ))
+      listOfSubMesh.push_back(sm);
 
-  static TopTools_ListOfShape emptyList;
-  return emptyList;
-}
-
-//=======================================================================
-//function : Dump
-//purpose  : dumps contents of mesh to stream [ debug purposes ]
-//=======================================================================
-ostream& SMESH_Mesh::Dump(ostream& save)
-{
-  save << "========================== Dump contents of mesh ==========================" << endl;
-  save << "1) Total number of nodes:     " << NbNodes() << endl;
-  save << "2) Total number of edges:     " << NbEdges() << endl;
-  save << "3) Total number of faces:     " << NbFaces() << endl;
-  if ( NbFaces() > 0 ) {
-    int nb3 = NbTriangles();
-    int nb4 = NbQuadrangles();
-    save << "3.1.) Number of triangles:    " << nb3 << endl;
-    save << "3.2.) Number of quadrangles:  " << nb4 << endl;
-    if ( nb3 + nb4 !=  NbFaces() ) {
-      map<int,int> myFaceMap;
-      SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
-      while( itFaces->more( ) ) {
-       int nbNodes = itFaces->next()->NbNodes();
-       if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
-         myFaceMap[ nbNodes ] = 0;
-       myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
-      }
-      save << "3.3.) Faces in detail: " << endl;
-      map <int,int>::iterator itF;
-      for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
-       save << "--> nb nodes: " << itF->first << " - nb elemens: " << itF->second << endl;
-    }
-  }
-  save << "4) Total number of volumes:   " << NbVolumes() << endl;
-  if ( NbVolumes() > 0 ) {
-    int nb8 = NbHexas();
-    int nb4 = NbTetras();
-    int nb5 = NbPyramids();
-    int nb6 = NbPrisms();
-    save << "4.1.) Number of hexahedrons:  " << nb8 << endl;
-    save << "4.2.) Number of tetrahedrons: " << nb4 << endl;
-    save << "4.3.) Number of prisms:       " << nb6 << endl;
-    save << "4.4.) Number of pyramides:    " << nb5 << endl;
-    if ( nb8 + nb4 + nb5 + nb6 != NbVolumes() ) {
-      map<int,int> myVolumesMap;
-      SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-      while( itVolumes->more( ) ) {
-       int nbNodes = itVolumes->next()->NbNodes();
-       if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
-         myVolumesMap[ nbNodes ] = 0;
-       myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
-      }
-      save << "4.5.) Volumes in detail: " << endl;
-      map <int,int>::iterator itV;
-      for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
-       save << "--> nb nodes: " << itV->first << " - nb elemens: " << itV->second << endl;
-    }
-  }
-  save << "===========================================================================" << endl;
-  return save;
-}
+  // sort submeshes according to stored mesh order
+  SortByMeshOrder( listOfSubMesh );
 
-//=======================================================================
-//function : GetElementType
-//purpose  : Returns type of mesh element with certain id
-//=======================================================================
-SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
-{
-  return _myMeshDS->GetElementType( id, iselem );
+  return listOfSubMesh;
 }