Salome HOME
Win32 compatibility
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 3988f2a236eef7e45d55c162a5af6ddcdde42140..aac87a540f26e24a594d6c852ca88b4508e7a38d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
@@ -55,6 +55,8 @@
 #include "DriverCGNS_Write.hxx"
 #endif
 
+#include <GEOMUtils.hxx>
+
 #undef _Precision_HeaderFile
 #include <BRepBndLib.hxx>
 #include <BRepPrimAPI_MakeBox.hxx>
 #include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 #include "Utils_ExceptHandlers.hxx"
+
 #ifndef WIN32
 #include <boost/thread/thread.hpp>
 #include <boost/bind.hpp>
 #else 
-#include <pthread.h> 
+#include <pthread.h>
 #endif
 
 using namespace std;
@@ -178,6 +181,23 @@ SMESH_Mesh::~SMESH_Mesh()
 {
   MESSAGE("SMESH_Mesh::~SMESH_Mesh");
 
+  // Unassign algorithms in order to have all SMESH_subMeshEventListenerData deleted (22874)
+  SMESHDS_SubMeshIteratorPtr smIt = _myMeshDS->SubMeshes();
+  while ( smIt->more() ) {
+    // avoid usual removal of elements while processing RemoveHypothesis( algo ) event
+    const_cast<SMESHDS_SubMesh*>( smIt->next() )->Clear();
+  }
+  const ShapeToHypothesis & hyps = _myMeshDS->GetHypotheses();
+  for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
+  {
+    const TopoDS_Shape& s = s2hyps.Key();
+    THypList         hyps = s2hyps.ChangeValue(); // copy
+    THypList::const_iterator h = hyps.begin();
+    for ( ; h != hyps.end(); ++h )
+      if ( (*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
+        RemoveHypothesis( s, (*h)->GetID() );
+  }
+
   // 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))
@@ -226,7 +246,7 @@ SMESH_Mesh::~SMESH_Mesh()
 
 bool SMESH_Mesh::MeshExists( int meshId ) const
 {
-  return _myDocument ? _myDocument->GetMesh( meshId ) : false;
+  return _myDocument ? bool( _myDocument->GetMesh( meshId )) : false;
 }
 
 //=============================================================================
@@ -327,8 +347,18 @@ double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
 {
   if ( !aShape.IsNull() ) {
     Bnd_Box Box;
-    BRepBndLib::Add(aShape, Box);
-    return sqrt( Box.SquareExtent() );
+    // avoid too long waiting on large shapes. PreciseBoundingBox() was added
+    // to assure same result which else depends on presence of triangulation (IPAL52557).
+    const int maxNbFaces = 4000;
+    int nbFaces = 0;
+    for ( TopExp_Explorer f( aShape, TopAbs_FACE ); f.More() && nbFaces < maxNbFaces; f.Next() )
+      ++nbFaces;
+    if ( nbFaces < maxNbFaces )
+      GEOMUtils::PreciseBoundingBox(aShape, Box);
+    else
+      BRepBndLib::Add( aShape, Box);
+    if ( !Box.IsVoid() )
+      return sqrt( Box.SquareExtent() );
   }
   return 0;
 }
@@ -601,12 +631,16 @@ SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName,
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
-                            int                  anHypId  ) throw(SALOME_Exception)
+SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
+                          int                  anHypId,
+                          std::string*         anError  ) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
 
+  if ( anError )
+    anError->clear();
+
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
   if ( !subMesh || !subMesh->GetId())
     return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
@@ -631,23 +665,36 @@ SMESH_Hypothesis::Hypothesis_Status
     }
   }
 
-  // shape 
+  // shape
 
-  bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
-  int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
+  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);
 
+  if ( anError && SMESH_Hypothesis::IsStatusFatal(ret) && subMesh->GetComputeError() )
+    *anError = subMesh->GetComputeError()->myComment;
+
   // sub-shapes
-  if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
-      anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
+  if ( !SMESH_Hypothesis::IsStatusFatal(ret) &&
+       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
   {
     event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
 
     SMESH_Hypothesis::Hypothesis_Status ret2 =
-      subMesh->SubMeshesAlgoStateEngine(event, anHyp);
+      subMesh->SubMeshesAlgoStateEngine(event, anHyp, /*exitOnFatal=*/true);
     if (ret2 > ret)
+    {
       ret = ret2;
+      if ( SMESH_Hypothesis::IsStatusFatal( ret ))
+      {
+        if ( anError && subMesh->GetComputeError() )
+          *anError = subMesh->GetComputeError()->myComment;
+        // remove anHyp
+        event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
+        subMesh->AlgoStateEngine(event, anHyp);
+      }
+    }
 
     // check concurent hypotheses on ancestors
     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
@@ -892,16 +939,19 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
     const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(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 )
+    {
+      const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
+      if (( aFilter.IsOk( h, aSubShape )) &&
+          ( h->IsAuxiliary() || !mainHypFound ) &&
+          ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
       {
         aHypList.push_back( *hyp );
         nbHyps++;
-        if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+        if ( !h->IsAuxiliary() )
           mainHypFound = true;
         if ( assignedTo ) assignedTo->push_back( aSubShape );
       }
+    }
   }
 
   // get hypos from ancestors of aSubShape
@@ -918,16 +968,19 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
       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          ))
+      {
+        const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
+        if (( aFilter.IsOk( h, curSh )) &&
+            ( h->IsAuxiliary() || !mainHypFound ) &&
+            ( h->IsAuxiliary() || hypTypes.insert( h->GetName() ).second ))
         {
           aHypList.push_back( *hyp );
           nbHyps++;
-          if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
+          if ( !h->IsAuxiliary() )
             mainHypFound = true;
           if ( assignedTo ) assignedTo->push_back( curSh );
         }
+      }
     }
   }
   return nbHyps;
@@ -984,6 +1037,8 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
   throw(SALOME_Exception)
 {
   int index = _myMeshDS->ShapeToIndex(aSubShape);
+  if ( !index && aSubShape.IsNull() )
+    return 0;
 
   // for submeshes on GEOM Group
   if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
@@ -996,14 +1051,29 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
         fillAncestorsMap( _myMeshDS->IndexToShape( ++_nbSubShapes ));
     }
   }
-//   if ( !index )
-//     return NULL; // neither sub-shape nor a group
+  // if ( !index )
+  //   return NULL; // neither sub-shape nor a group
 
   SMESH_subMesh* aSubMesh = _subMeshHolder->Get( index );
   if ( !aSubMesh )
   {
     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
     _subMeshHolder->Add( index, aSubMesh );
+
+    // include non-computable sub-meshes in SMESH_subMesh::_ancestors of sub-submeshes
+    switch ( aSubShape.ShapeType() ) {
+    case TopAbs_COMPOUND:
+    case TopAbs_WIRE:
+    case TopAbs_SHELL:
+      for ( TopoDS_Iterator subIt( aSubShape ); subIt.More(); subIt.Next() )
+      {
+        SMESH_subMesh* sm = GetSubMesh( subIt.Value() );
+        SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*inclideSelf=*/true);
+        while ( smIt->more() )
+          smIt->next()->ClearAncestors();
+      }
+    default:;
+    }
   }
   return aSubMesh;
 }
@@ -1157,6 +1227,9 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   const SMESH_HypoFilter* compatibleHypoKind;
   list <const SMESHDS_Hypothesis * > usedHyps;
 
+  // keep sub-meshes not to miss ones whose state can change due to notifying others
+  vector< SMESH_subMesh* > smToNotify;
+
   SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   while ( smIt->more() )
   {
@@ -1169,7 +1242,8 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
     // other possible changes are not interesting. (IPAL0052457 - assigning hyp performance pb)
     if ( aSubMesh->GetComputeState() != SMESH_subMesh::COMPUTE_OK &&
          aSubMesh->GetComputeState() != SMESH_subMesh::FAILED_TO_COMPUTE &&
-         aSubMesh->GetAlgoState()    != SMESH_subMesh::MISSING_HYP )
+         aSubMesh->GetAlgoState()    != SMESH_subMesh::MISSING_HYP &&
+         !hyp->DataDependOnParams() )
       continue;
 
     const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
@@ -1184,11 +1258,17 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
       if ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
            find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
       {
-        aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
-                                  const_cast< SMESH_Hypothesis*>( hyp ));
+        smToNotify.push_back( aSubMesh );
       }
     }
   }
+
+  for ( size_t i = 0; i < smToNotify.size(); ++i )
+  {
+    smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
+                                   const_cast< SMESH_Hypothesis*>( hyp ));
+  }
+
   HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
   GetMeshDS()->Modified();
 }
@@ -1818,6 +1898,18 @@ int SMESH_Mesh::NbSubMesh() const throw(SALOME_Exception)
   return _myMeshDS->NbSubMesh();
 }
 
+//================================================================================
+/*!
+ * \brief Returns number of meshes in the Study, that is supposed to be
+ *        equal to SMESHDS_Document::NbMeshes()
+ */
+//================================================================================
+
+int SMESH_Mesh::NbMeshes() const // nb meshes in the Study
+{
+  return _myDocument->NbMeshes();
+}
+
 //=======================================================================
 //function : IsNotConformAllowed
 //purpose  : check if a hypothesis alowing notconform mesh is present
@@ -2185,12 +2277,10 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
         while ( ancIt.More() && ancIt.Value().ShapeType() >= memberType )
           ancIt.Next();
         if ( ancIt.More() )
-        {
           ancList.InsertBefore( theShape, ancIt );
-          GetSubMesh( des.Current() )->ClearAncestors(); // to re-fill _ancestors
-        }
       }
   }
+  else // else added for 52457: Addition of hypotheses is 8 time longer than meshing
   {
     for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
       for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
@@ -2202,9 +2292,11 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
   // visit COMPOUNDs inside a COMPOUND that are not reachable by TopExp_Explorer
   if ( theShape.ShapeType() == TopAbs_COMPOUND )
   {
-    for ( TopoDS_Iterator sIt(theShape); sIt.More(); sIt.Next() )
-      if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
-        fillAncestorsMap( sIt.Value() );
+    TopoDS_Iterator sIt(theShape);
+    if ( sIt.More() && sIt.Value().ShapeType() == TopAbs_COMPOUND )
+      for ( ; sIt.More(); sIt.Next() )
+        if ( sIt.Value().ShapeType() == TopAbs_COMPOUND )
+          fillAncestorsMap( sIt.Value() );
   }
 }