Salome HOME
Replaced NMTTools map with NCollection map for removing dependencies from GEOM module.
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index eb0f0392df127cf163d191336af218de0d2e3ea9..d4497448fd32b96f40963be8cfc1e179cf23d757 100644 (file)
@@ -31,6 +31,7 @@
 #include "SMESH_Gen.hxx"
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Group.hxx"
+#include "SMESH_HypoFilter.hxx"
 #include "SMESHDS_Group.hxx"
 #include "SMESHDS_Script.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
@@ -56,6 +57,7 @@
 #include <TopTools_ListOfShape.hxx>
 #include <TopTools_Array1OfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 
 #include <memory>
 
@@ -134,7 +136,6 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
       else
         i_gr++;
     }
-    _mapAncestors.Clear();
     _mapPropagationChains.Clear();
   }
   else
@@ -144,6 +145,17 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
   }
   _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 );
+
   // NRI : 24/02/03
   //EAP: 1/9/04 TopExp::MapShapes(aShape, _subShapes); USE the same map of _myMeshDS
 }
@@ -255,14 +267,17 @@ SMESH_Hypothesis::Hypothesis_Status
 
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
-  if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
+  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;
@@ -368,6 +383,8 @@ SMESH_Hypothesis::Hypothesis_Status
     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;
@@ -462,6 +479,87 @@ SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
   return _myMeshDS->GetHypothesis(aSubShape);
 }
 
+//=======================================================================
+//function : GetHypothesis
+//purpose  : 
+//=======================================================================
+
+const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
+                                                   const SMESH_HypoFilter& aFilter,
+                                                   const bool              andAncestors) 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))
+        return h;
+    }
+  }
+  if ( andAncestors )
+  {
+    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
+    for (; it.More(); it.Next() )
+    {
+      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      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() ))
+          return h;
+      }
+    }
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : GetHypotheses
+//purpose  : 
+//=======================================================================
+
+bool SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
+                               const SMESH_HypoFilter&             aFilter,
+                               list <const SMESHDS_Hypothesis * >& aHypList,
+                               const bool                          andAncestors) const
+{
+  int nbHyp = 0;
+  {
+    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)) {
+        aHypList.push_back( *hyp );
+        nbHyp++;
+      }
+  }
+  // get hypos from shape of one type only: if any hypo is found on edge, do
+  // not look up on faces
+  if ( !nbHyp && andAncestors )
+  {
+    TopTools_MapOfShape map;
+    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
+    int shapeType = it.More() ? it.Value().ShapeType() : TopAbs_SHAPE;
+    for (; it.More(); it.Next() )
+    {
+      if ( nbHyp && shapeType != it.Value().ShapeType() )
+        break;
+      shapeType = it.Value().ShapeType();
+      if ( !map.Add( it.Value() ))
+        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++;
+      }
+    }
+  }
+  return nbHyp;
+}
+
 //=============================================================================
 /*!
  * 
@@ -567,6 +665,24 @@ throw(SALOME_Exception)
   return aSubMesh;
 }
 
+//=============================================================================
+/*!
+ * Get the SMESH_subMesh object implementation. Dont create it, return null
+ * if it does not exist.
+ */
+//=============================================================================
+
+SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID)
+throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  
+  map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(aShapeID);
+  if (i_sm == _mapSubMesh.end())
+    return NULL;
+  return i_sm->second;
+}
+
 //=======================================================================
 //function : IsUsedHypothesis
 //purpose  : Return True if anHyp is used to mesh aSubShape
@@ -575,10 +691,10 @@ throw(SALOME_Exception)
 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
                                   const TopoDS_Shape & aSubShape)
 {
+  SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
   // check if anHyp is applicable to aSubShape
   SMESH_subMesh * subMesh = GetSubMeshContaining( aSubShape );
-  if (!subMesh ||
-      !subMesh->IsApplicableHypotesis(static_cast<SMESH_Hypothesis*>(anHyp)))
+  if ( !subMesh || !subMesh->IsApplicableHypotesis( hyp ))
     return false;
 
   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape);
@@ -593,37 +709,12 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
     // look trough hypotheses used by algo
     const list <const SMESHDS_Hypothesis * >&usedHyps =
       algo->GetUsedHypothesis(*this, aSubShape);
-    list <const SMESHDS_Hypothesis * >::const_iterator itl;
-    for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
-      if (anHyp == (*itl))
-        return true;
+    return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
   }
-  else
-  {
-    // look through all assigned hypotheses
-    {
-      const list <const SMESHDS_Hypothesis * >&usedHyps =
-        _myMeshDS->GetHypothesis( aSubShape );
-      list <const SMESHDS_Hypothesis * >::const_iterator itl;
-      for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
-        if (anHyp == (*itl))
-          return true;
-    }
 
-    // on ancestors
-    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
-    for (; it.More(); it.Next())
-    {
-      const list <const SMESHDS_Hypothesis * >&usedHyps =
-        _myMeshDS->GetHypothesis( aSubShape );
-      list <const SMESHDS_Hypothesis * >::const_iterator itl;
-      for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
-        if (anHyp == (*itl))
-          return true;
-    }
-  }
-    
-  return false;
+  // look through all assigned hypotheses
+  SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
+  return GetHypothesis( aSubShape, filter, true );
 }
 
 
@@ -765,7 +856,12 @@ int SMESH_Mesh::NbTriangles() throw(SALOME_Exception)
   int Nb = 0;
   
   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
-  while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++;
+  //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;
 }
 
@@ -778,7 +874,25 @@ int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception)
   int Nb = 0;
   
   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
-  while(itFaces->more()) if(itFaces->next()->NbNodes()==4) Nb++;
+  //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 the number of polygonal faces in the mesh. This method run in O(n)
+///////////////////////////////////////////////////////////////////////////////
+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;
 }
 
@@ -798,7 +912,12 @@ int SMESH_Mesh::NbTetras() throw(SALOME_Exception)
   Unexpect aCatch(SalomeException);
   int Nb = 0;
   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++;
+  //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;
 }
 
@@ -807,7 +926,12 @@ int SMESH_Mesh::NbHexas() throw(SALOME_Exception)
   Unexpect aCatch(SalomeException);
   int Nb = 0;
   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++;
+  //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;
 }
 
@@ -816,7 +940,12 @@ int SMESH_Mesh::NbPyramids() throw(SALOME_Exception)
   Unexpect aCatch(SalomeException);
   int Nb = 0;
   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++;
+  //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;
 }
 
@@ -825,7 +954,22 @@ int SMESH_Mesh::NbPrisms() throw(SALOME_Exception)
   Unexpect aCatch(SalomeException);
   int Nb = 0;
   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
-  while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++;
+  //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;
+}
+
+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;
 }
 
@@ -849,18 +993,8 @@ bool SMESH_Mesh::IsNotConformAllowed() const
 {
   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
 
-  const list<const SMESHDS_Hypothesis*>& listHyp =
-    _myMeshDS->GetHypothesis( _myMeshDS->ShapeToMesh() );
-  list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
-  while (it!=listHyp.end())
-  {
-    const SMESHDS_Hypothesis *aHyp = *it;
-    string hypName = aHyp->GetName();
-    if ( hypName == "NotConformAllowed" )
-      return true;
-    it++;
-  }
-  return false;
+  SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
+  return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
 }
 
 //=======================================================================
@@ -941,23 +1075,15 @@ void SMESH_Mesh::RemoveGroup (const int theGroupID)
 //=============================================================================
 /*!
  *  IsLocal1DHypothesis
- *  Check, if there is 1D hypothesis assigned directly on <theEdge>
+ *  Returns a local 1D hypothesis used for theEdge
  */
 //=============================================================================
-bool SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
+const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
 {
-  const SMESHDS_Mesh* meshDS = GetMeshDS();
-  const list<const SMESHDS_Hypothesis*>& listHyp = meshDS->GetHypothesis(theEdge);
-  list<const SMESHDS_Hypothesis*>::const_iterator it = listHyp.begin();
-
-  for (; it != listHyp.end(); it++) {
-    const SMESH_Hypothesis * aHyp = static_cast<const SMESH_Hypothesis*>(*it);
-    if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO &&
-        aHyp->GetDim() == 1) { // 1D Hypothesis found
-      return true;
-    }
-  }
-  return false;
+  SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
+  hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() ));
+
+  return GetHypothesis( theEdge, hypo, true );
 }
 
 //=============================================================================
@@ -980,7 +1106,8 @@ bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge,
 {
   int nbChains = _mapPropagationChains.Extent();
   for (int i = 1; i <= nbChains; i++) {
-    const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(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;
@@ -1001,7 +1128,7 @@ bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
   if ( !theMainEdge.IsNull() && !theEdge.IsNull() &&
       _mapPropagationChains.Contains( theMainEdge ))
   {
-    const TopTools_IndexedMapOfShape& aChain =
+    const SMESH_IndexedMapOfShape& aChain =
       _mapPropagationChains.FindFromKey( theMainEdge );
     int index = aChain.FindIndex( theEdge );
     if ( index )
@@ -1017,7 +1144,7 @@ bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
 //=============================================================================
 void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge)
 {
-  const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(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);
@@ -1078,11 +1205,15 @@ bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge)
 
   // Remove the chain from the map
   int i = _mapPropagationChains.FindIndex(theMainEdge);
-  TopoDS_Vertex anEmptyShape;
-  BRep_Builder BB;
-  BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1);
-  TopTools_IndexedMapOfShape anEmptyMap;
-  _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap);
+  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;
 }
@@ -1098,18 +1229,19 @@ bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
 
   // Add new chain, if there is no
   if (!_mapPropagationChains.Contains(theMainEdge)) {
-    TopTools_IndexedMapOfShape aNewChain;
+    SMESH_IndexedMapOfShape aNewChain;
     _mapPropagationChains.Add(theMainEdge, aNewChain);
   }
 
   // Check presence of 1D hypothesis to be propagated
-  if (!IsLocal1DHypothesis(theMainEdge)) {
+  const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge);
+  if (!aMainHyp) {
     MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign.");
     return true;
   }
 
   // Edges, on which the 1D hypothesis will be propagated from <theMainEdge>
-  TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
+  SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
   if (aChain.Extent() > 0) {
     CleanMeshOnPropagationChain(theMainEdge);
     aChain.Clear();
@@ -1177,18 +1309,14 @@ bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
             if (opp > 4) opp -= 4;
             anOppE = anEdges(opp);
 
-            if (!aChain.Contains(anOppE)) {
-              if (!IsLocal1DHypothesis(anOppE)) {
-                TopoDS_Shape aMainEdgeForOppEdge;
-                if (IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge)) {
-                  // Collision!
-                  MESSAGE("Error: Collision between propagated hypotheses");
-                  CleanMeshOnPropagationChain(theMainEdge);
-                  aChain.Clear();
-                  return false;
-                } else {
+            // 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 in aChain co-directed with theMainEdge
+                  // have it co-directed with a forward MainEdge
                   TopAbs_Orientation ori = anE.Orientation();
                   if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
                     ori = TopAbs::Reverse( ori );
@@ -1196,6 +1324,13 @@ bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
                   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)
@@ -1216,20 +1351,8 @@ bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
 //           that lower dimention shapes come first.
 //=======================================================================
 
-const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS)
+const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
 {
-  if ( _mapAncestors.IsEmpty() )
-  {
-    // fill _mapAncestors
-    int desType, ancType;
-    for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- )
-      for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
-        TopExp::MapShapesAndAncestors (_myMeshDS->ShapeToMesh(),
-                                       (TopAbs_ShapeEnum) desType,
-                                       (TopAbs_ShapeEnum) ancType,
-                                       _mapAncestors );
-  }
-
   if ( _mapAncestors.Contains( theS ) )
     return _mapAncestors.FindFromKey( theS );
 
@@ -1295,3 +1418,12 @@ ostream& SMESH_Mesh::Dump(ostream& save)
   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 );
+}