Salome HOME
Merge from BR_phase16 branch (09/12/09)
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 866fda73926e79edab0079252b506292f3b302d2..6b2a69bcc4ad6aa01b1627855e01d81c612cf1e6 100644 (file)
@@ -81,11 +81,11 @@ typedef SMESH_HypoFilter THypType;
 //=============================================================================
 
 SMESH_Mesh::SMESH_Mesh(int               theLocalId, 
-                      int               theStudyId, 
-                      SMESH_Gen*        theGen,
-                      bool              theIsEmbeddedMode,
-                      SMESHDS_Document* theDocument):
-  _groupId( 0 )
+                       int               theStudyId, 
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument):
+  _groupId( 0 ), _nbSubShapes( 0 )
 {
   MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
   _id            = theLocalId;
@@ -110,6 +110,11 @@ 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
   std::map < int, SMESH_Group * >::iterator itg;
   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
@@ -129,9 +134,11 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
 {
   if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh");
 
-  if ( !aShape.IsNull() && _isShapeToMesh )
-    throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
-
+  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() )
   {
@@ -166,15 +173,16 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
   {
     _myMeshDS->ShapeToMesh(aShape);
     _isShapeToMesh = true;
+    _nbSubShapes = _myMeshDS->MaxShapeIndex();
 
-    // fill _mapAncestors
-    int desType, ancType;
-    for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
-      for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
-        TopExp::MapShapesAndAncestors ( aShape,
-                                        (TopAbs_ShapeEnum) desType,
-                                        (TopAbs_ShapeEnum) ancType,
-                                        _mapAncestors );
+    // fill map of ancestors
+    fillAncestorsMap(aShape);
+  }
+  else
+  {
+    _isShapeToMesh = false;
+    _shapeDiagonal = 0.0;
+    _myMeshDS->ShapeToMesh( PseudoShape() );
   }
 }
 
@@ -311,14 +319,14 @@ void SMESH_Mesh::ClearSubMesh(const int theShapeId)
   if ( SMESH_subMesh *sm = GetSubMeshContaining( theShapeId ) )
   {
     SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
-                                                            /*complexShapeFirst=*/false);
+                                                             /*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 );
+        // 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 );
     }
@@ -359,21 +367,21 @@ int SMESH_Mesh::UNVToMesh(const char* theFileName)
 
       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());
-       }
+        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());
+        }
       }
     }
   }
@@ -465,33 +473,6 @@ SMESH_Hypothesis::Hypothesis_Status
   if ( !subMesh || !subMesh->GetId())
     return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
 
-  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;
-    }
-    // bind hypotheses to a group just to know
-    SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId];
-    GetMeshDS()->AddHypothesis( aSubShape, anHyp );
-
-    if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
-      return aBestRet;
-    return aWorstNotFatal;
-  }
-
   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
   {
@@ -572,32 +553,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;
-    }
-    SMESH_Hypothesis *anHyp = _gen->GetStudyContext(_studyId)->mapHypothesis[anHypId];
-    GetMeshDS()->RemoveHypothesis( aSubShape, anHyp );
-
-    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"));
@@ -611,6 +566,8 @@ SMESH_Hypothesis::Hypothesis_Status
   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
@@ -695,15 +652,18 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubS
   }
   if ( andAncestors )
   {
-    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
-    for (; it.More(); it.Next() )
+    // user sorted submeshes of ancestors, according to stored submesh priority
+    const std::list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    std::list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
+    for ( ; smIt != smList.end(); smIt++ )
     {
-      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
+      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
       for ( ; hyp != hypList.end(); hyp++ ) {
         const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
-        if (aFilter.IsOk( h, it.Value() )) {
-          if ( assignedTo ) *assignedTo = it.Value();
+        if (aFilter.IsOk( h, curSh )) {
+          if ( assignedTo ) *assignedTo = curSh;
           return h;
         }
       }
@@ -762,14 +722,18 @@ int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
   if ( andAncestors )
   {
     TopTools_MapOfShape map;
-    TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
-    for (; it.More(); it.Next() )
+
+    // user sorted submeshes of ancestors, according to stored submesh priority
+    const std::list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
+    std::list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
+    for ( ; smIt != smList.end(); smIt++ )
     {
-     if ( !map.Add( it.Value() ))
+      const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
+     if ( !map.Add( curSh ))
         continue;
-      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
+      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
-        if (aFilter.IsOk( cSMESH_Hyp( *hyp ), it.Value() ) &&
+        if (aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh ) &&
             ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
             hypTypes.insert( (*hyp)->GetName() ).second )
         {
@@ -822,10 +786,16 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
   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
+
+      // fill map of Ancestors
+      fillAncestorsMap(aSubShape);
+    }
   }
 //   if ( !index )
 //     return NULL; // neither sub-shape nor a group
@@ -839,6 +809,7 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
   {
     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
     _mapSubMesh[index] = aSubMesh;
+    ClearMeshOrder();
   }
   return aSubMesh;
 }
@@ -1069,9 +1040,9 @@ bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
 }
 
 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);
@@ -1178,6 +1149,18 @@ int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
  */
 //================================================================================
 
+int SMESH_Mesh::Nb0DElements() throw(SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  return _myMeshDS->GetMeshInfo().Nb0DElements();
+}
+
+//================================================================================
+/*!
+ * \brief  Return number of edges of given order in the mesh
+ */
+//================================================================================
+
 int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
@@ -1347,7 +1330,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())
@@ -1551,3 +1534,138 @@ SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
   return aGroup;
 }
 
+//=============================================================================
+/*!
+ *  \brief remove submesh order  from Mesh
+ */
+//=============================================================================
+
+void SMESH_Mesh::ClearMeshOrder()
+{
+  _mySubMeshOrder.clear();
+}
+
+//=============================================================================
+/*!
+ *  \brief remove submesh order  from Mesh
+ */
+//=============================================================================
+
+void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
+{
+  _mySubMeshOrder = theOrder;
+}
+
+//=============================================================================
+/*!
+ *  \brief return submesh order if any
+ */
+//=============================================================================
+
+const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
+{
+  return _mySubMeshOrder;
+}
+
+//=============================================================================
+/*!
+ *  \brief fillAncestorsMap
+ */
+//=============================================================================
+
+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 );
+}
+
+//=============================================================================
+/*!
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
+ */
+//=============================================================================
+
+bool SMESH_Mesh::SortByMeshOrder(std::list<SMESH_subMesh*>& theListToSort) const
+{
+  if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
+    return true;
+  
+  bool res = false;
+  std::list<SMESH_subMesh*> onlyOrderedList;
+  // collect all ordered submeshes in one list as pointers
+  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++ ) {
+      map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(*idIt);
+      if ( i_sm != _mapSubMesh.end() )
+        onlyOrderedList.push_back(i_sm->second);
+    }
+  }
+  if (!onlyOrderedList.size())
+    return res;
+
+  std::list<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+  std::list<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+
+  // check positions where ordered submeshes should be in result list
+  std::set<int> setOfPos; // remember positions of in set
+  std::list<SMESH_subMesh*>::const_iterator smIt = theListToSort.begin();
+  int i = 0;
+  for( ; smIt != theListToSort.end(); i++, smIt++ )
+    if ( find( onlyBIt, onlyEIt, *smIt ) != onlyEIt )
+      setOfPos.insert(i);
+
+  if ( !setOfPos.size() )
+    return res;
+
+  // new list of all submeshes to be sorted
+  std::list<SMESH_subMesh*> aNewList;
+  // iterates on submeshes and insert ordered in detected positions
+  for ( i = 0, smIt = theListToSort.begin(); smIt != theListToSort.end(); i++, smIt++ )
+    if ( setOfPos.find( i ) != setOfPos.end() &&
+         onlyBIt != onlyEIt ) { // position of ordered submesh detected
+      aNewList.push_back( *onlyBIt ); // ordered submesh
+      onlyBIt++;
+    }
+    else
+      aNewList.push_back( *smIt ); // other submesh from list
+  
+  theListToSort = aNewList;
+  return res;
+}
+
+//=============================================================================
+/*!
+ * \brief sort submeshes according to stored mesh order
+ * \param theListToSort in out list to be sorted
+ * \return FALSE if nothing sorted
+ */
+//=============================================================================
+
+std::list<SMESH_subMesh*> SMESH_Mesh::getAncestorsSubMeshes
+  (const TopoDS_Shape& theSubShape) const
+{
+  std::list<SMESH_subMesh*> listOfSubMesh;
+  TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
+  for (; it.More(); it.Next() ) {
+    int index = _myMeshDS->ShapeToIndex(it.Value());
+    map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
+    if (i_sm != _mapSubMesh.end())
+      listOfSubMesh.push_back(i_sm->second);
+  }
+
+  // sort submeshes according to stored mesh order
+  SortByMeshOrder( listOfSubMesh );
+
+  return listOfSubMesh;
+}