Salome HOME
Merge from V5_1_main branch 24/11/2010
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index 6c484c80a20e6d9eff3ddef37a83010a4532a7c4..69b33a94c85ad2861a6576b10c4a08d373140705 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  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
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_subMesh.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
-//  $Header$
 //
 #include "SMESH_subMesh.hxx"
 
 #include "SMESH_subMeshEventListener.hxx"
 #include "SMESH_Comment.hxx"
 #include "SMDS_SetIterator.hxx"
+#include "SMDSAbs_ElementType.hxx"
 
 #include "utilities.h"
 #include "OpUtil.hxx"
+#include "Basics_Utils.hxx"
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
@@ -54,6 +56,8 @@
 #include <Standard_OutOfMemory.hxx>
 #include <Standard_ErrorHandler.hxx>
 
+#include <numeric>
+
 using namespace std;
 
 //=============================================================================
@@ -82,22 +86,22 @@ SMESH_subMesh::SMESH_subMesh(int                  Id,
                              SMESHDS_Mesh *       meshDS,
                              const TopoDS_Shape & aSubShape)
 {
-       _subShape = aSubShape;
-       _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
-       _father = father;
-       _Id = Id;
-       _dependenceAnalysed = _alwaysComputed = false;
-
-       if (_subShape.ShapeType() == TopAbs_VERTEX)
-       {
-               _algoState = HYP_OK;
-               _computeState = READY_TO_COMPUTE;
-       }
-       else
-       {
+        _subShape = aSubShape;
+        _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
+        _father = father;
+        _Id = Id;
+        _dependenceAnalysed = _alwaysComputed = false;
+
+        if (_subShape.ShapeType() == TopAbs_VERTEX)
+        {
+                _algoState = HYP_OK;
+                _computeState = READY_TO_COMPUTE;
+        }
+        else
+        {
           _algoState = NO_ALGO;
           _computeState = NOT_READY;
-       }
+        }
 }
 
 //=============================================================================
@@ -261,7 +265,7 @@ bool SMESH_subMesh::SubMeshesComputed()
       break; // the rest subMeshes are all of less dimension
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-                      (ds && ( ds->NbNodes() || ds->NbElements() )));
+                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes()  )));
     if (!computeOk)
     {
       int type = ss.ShapeType();
@@ -368,23 +372,24 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_COMPOUND:
     {
       //MESSAGE("compound");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next())
       {
+        if ( BRep_Tool::IsClosed(exp.Current() ))
           InsertDependence(exp.Current());      //only shell not in solid
+        else
+          for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next())
+            InsertDependence(expF.Current());    // issue 0020959: HEXA_3D fails on shell
+
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -392,9 +397,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
     }
   case TopAbs_COMPSOLID:
     {
-               //MESSAGE("compsolid");
-      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
-           exp.Next())
+      //MESSAGE("compsolid");
+      for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -403,8 +407,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_SHELL:
     {
       //MESSAGE("shell");
-      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -413,8 +416,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_WIRE:
     {
       //MESSAGE("wire");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -424,8 +426,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
     {
       //MESSAGE("solid");
       if(_father->HasShapeToMesh()) {
-        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
-             exp.Next())
+        for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
         {
           InsertDependence(exp.Current());
         }
@@ -435,8 +436,7 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_FACE:
     {
       //MESSAGE("face");
-      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
       {
         InsertDependence(exp.Current());
       }
@@ -445,11 +445,10 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   case TopAbs_EDGE:
     {
       //MESSAGE("edge");
-      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More();
-           exp.Next())
+      for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
       {
-                       InsertDependence(exp.Current());
-                      }
+        InsertDependence(exp.Current());
+      }
       break;
     }
   case TopAbs_VERTEX:
@@ -495,8 +494,8 @@ void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
 
 const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
 {
-       //MESSAGE("SMESH_subMesh::GetSubShape");
-       return _subShape;
+        //MESSAGE("SMESH_subMesh::GetSubShape");
+        return _subShape;
 }
 
 
@@ -609,6 +608,7 @@ SMESH_Hypothesis::Hypothesis_Status
 
   int oldAlgoState = _algoState;
   bool modifiedHyp = (event == MODIF_HYP);  // if set to true, force event MODIF_ALGO_STATE
+  bool needFullClean = false;
 
   bool isApplicableHyp = IsApplicableHypotesis( anHyp );
 
@@ -625,6 +625,15 @@ SMESH_Hypothesis::Hypothesis_Status
     // ----------------------
     if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
       return SMESH_Hypothesis::HYP_NOTCONFORM;
+
+    // check if all-dimensional algo is hidden by other local one
+    if ( event == ADD_ALGO ) {
+      SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
+      filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
+      filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
+      if ( SMESH_Algo * curAlgo = (SMESH_Algo*) _father->GetHypothesis( _subShape, filter, true ))
+        needFullClean = ( !curAlgo->NeedDescretBoundary() );
+    }
   }
 
   // ----------------------------------
@@ -658,10 +667,7 @@ SMESH_Hypothesis::Hypothesis_Status
         // clean all mesh in the tree of the current submesh;
         // we must perform it now because later
         // we will have no information about the type of the removed algo
-        CleanDependants();
-       ComputeStateEngine( CLEAN );
-        CleanDependsOn();
-        ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+        needFullClean = true;
       }
     }
   }
@@ -940,6 +946,12 @@ SMESH_Hypothesis::Hypothesis_Status
       break;
     }
     case REMOVE_FATHER_ALGO: {
+      // IPAL21346. Edges not removed when Netgen 1d-2d is removed from a SOLID.
+      // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID.
+      algo = dynamic_cast<SMESH_Algo*> (anHyp);
+      if (!algo->NeedDescretBoundary())
+        needFullClean = true;
+
       algo = gen->GetAlgo((*_father), _subShape);
       if (algo == NULL)  // no more applying algo on father
       {
@@ -988,9 +1000,12 @@ SMESH_Hypothesis::Hypothesis_Status
     if ( ret == SMESH_Hypothesis::HYP_OK &&
          !algo->NeedDescretBoundary()    &&
          !algo->SupportSubmeshes()) {
+      TopoDS_Shape algoAssignedTo, otherAssignedTo;
+      gen->GetAlgo( *_father, _subShape, &algoAssignedTo );
       map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
       for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
-        if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
+        if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) &&
+             SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
           ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
     }
   }
@@ -1012,6 +1027,13 @@ SMESH_Hypothesis::Hypothesis_Status
     }
   }
 
+  if ( needFullClean ) {
+    // added or removed algo is all-dimensional
+    ComputeStateEngine( CLEAN );
+    CleanDependsOn();
+    ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
+  }
+
   if (stateChange || modifiedHyp)
     ComputeStateEngine(MODIF_ALGO_STATE);
 
@@ -1128,48 +1150,48 @@ void SMESH_subMesh::CleanDependsOn()
 
 void SMESH_subMesh::DumpAlgoState(bool isMain)
 {
-       int dim = SMESH_Gen::GetShapeDim(_subShape);
+        int dim = SMESH_Gen::GetShapeDim(_subShape);
 //   if (dim < 1) return;
-       if (isMain)
-       {
-               const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
-
-               map < int, SMESH_subMesh * >::const_iterator itsub;
-               for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
-               {
-                       SMESH_subMesh *sm = (*itsub).second;
-                       sm->DumpAlgoState(false);
-               }
-       }
-       int type = _subShape.ShapeType();
-       MESSAGE("dim = " << dim << " type of shape " << type);
-       switch (_algoState)
-       {
-       case NO_ALGO:
-               MESSAGE(" AlgoState = NO_ALGO");
-               break;
-       case MISSING_HYP:
-               MESSAGE(" AlgoState = MISSING_HYP");
-               break;
-       case HYP_OK:
-               MESSAGE(" AlgoState = HYP_OK");
-               break;
-       }
-       switch (_computeState)
-       {
-       case NOT_READY:
-               MESSAGE(" ComputeState = NOT_READY");
-               break;
-       case READY_TO_COMPUTE:
-               MESSAGE(" ComputeState = READY_TO_COMPUTE");
-               break;
-       case COMPUTE_OK:
-               MESSAGE(" ComputeState = COMPUTE_OK");
-               break;
-       case FAILED_TO_COMPUTE:
-               MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
-               break;
-       }
+        if (isMain)
+        {
+                const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
+
+                map < int, SMESH_subMesh * >::const_iterator itsub;
+                for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
+                {
+                        SMESH_subMesh *sm = (*itsub).second;
+                        sm->DumpAlgoState(false);
+                }
+        }
+        int type = _subShape.ShapeType();
+        MESSAGE("dim = " << dim << " type of shape " << type);
+        switch (_algoState)
+        {
+        case NO_ALGO:
+                MESSAGE(" AlgoState = NO_ALGO");
+                break;
+        case MISSING_HYP:
+                MESSAGE(" AlgoState = MISSING_HYP");
+                break;
+        case HYP_OK:
+                MESSAGE(" AlgoState = HYP_OK");
+                break;
+        }
+        switch (_computeState)
+        {
+        case NOT_READY:
+                MESSAGE(" ComputeState = NOT_READY");
+                break;
+        case READY_TO_COMPUTE:
+                MESSAGE(" ComputeState = READY_TO_COMPUTE");
+                break;
+        case COMPUTE_OK:
+                MESSAGE(" ComputeState = COMPUTE_OK");
+                break;
+        case FAILED_TO_COMPUTE:
+                MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
+                break;
+        }
 }
 
 //================================================================================
@@ -1264,13 +1286,13 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       if ( _algoState == HYP_OK )
         _computeState = READY_TO_COMPUTE;
       break;
-    case COMPUTE:              // nothing to do
+    case COMPUTE:               // nothing to do
       break;
     case CLEAN:
       CleanDependants();
       RemoveSubMeshElementsAndNodes();
       break;
-    case SUBMESH_COMPUTED:     // nothing to do
+    case SUBMESH_COMPUTED:      // nothing to do
       break;
     case SUBMESH_RESTORED:
       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
@@ -1348,6 +1370,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           algo->InitComputeError();
           MemoryReserve aMemoryReserve;
           SMDS_Mesh::CheckMemory();
+          Kernel_Utils::Localizer loc;
           if ( !_father->HasShapeToMesh() ) // no shape
           {
             SMESH_MesherHelper helper( *_father );
@@ -1405,18 +1428,29 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             ret = false;
         }
-        if (ret && !_alwaysComputed && shape == _subShape) { // check if anything was built
-          ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
+        TopExp_Explorer subS(shape, _subShape.ShapeType());
+        if (ret) // check if anything was built
+        {
+          for (; ret && subS.More(); subS.Next())
+            ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed();
         }
         bool isComputeErrorSet = !CheckComputeError( algo, shape );
         if (!ret && !isComputeErrorSet)
         {
           // Set _computeError
-          if ( !_computeError )
-            _computeError = SMESH_ComputeError::New();
-          if ( _computeError->IsOK() )
-            _computeError->myName = COMPERR_ALGO_FAILED;
-          _computeState = FAILED_TO_COMPUTE;
+          for (subS.ReInit(); subS.More(); subS.Next())
+          {
+            SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+            if ( !sm->IsMeshComputed() )
+            {
+              if ( !sm->_computeError )
+                sm->_computeError = SMESH_ComputeError::New();
+              if ( sm->_computeError->IsOK() )
+                sm->_computeError->myName = COMPERR_ALGO_FAILED;
+              sm->_computeState = FAILED_TO_COMPUTE;
+              sm->_computeError->myAlgo = algo;
+            }
+          }
         }
         if (ret)
         {
@@ -1513,6 +1547,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     switch (event)
     {
     case MODIF_ALGO_STATE:
+      if ( !IsEmpty() )
+        ComputeStateEngine( CLEAN );
       algo = gen->GetAlgo((*_father), _subShape);
       if (algo && !algo->NeedDescretBoundary())
         CleanDependsOn(); // clean sub-meshes with event CLEAN
@@ -1564,6 +1600,63 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
   return ret;
 }
 
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
+{
+  _computeError.reset();
+
+  bool ret = true;
+
+  if (_subShape.ShapeType() == TopAbs_VERTEX) {
+    vector<int> aVec(SMDSEntity_Last,0);
+    aVec[SMDSEntity_Node] = 1;
+    aResMap.insert(make_pair(this,aVec));
+    return ret;
+  }
+
+  SMESH_Gen *gen = _father->GetGen();
+  SMESH_Algo *algo = 0;
+  SMESH_Hypothesis::Hypothesis_Status hyp_status;
+
+  algo = gen->GetAlgo((*_father), _subShape);
+  if(algo && !aResMap.count(this) )
+  {
+    ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
+    if (!ret) return false;
+
+    if (_father->HasShapeToMesh() && algo->NeedDescretBoundary())
+    {
+      // check submeshes needed
+      bool subMeshEvaluated = true;
+      int dimToCheck = SMESH_Gen::GetShapeDim( _subShape ) - 1;
+      SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,/*complexShapeFirst=*/true);
+      while ( smIt->more() && subMeshEvaluated )
+      {
+        SMESH_subMesh* sm = smIt->next();
+        int dim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
+        if (dim < dimToCheck) break; // the rest subMeshes are all of less dimension
+        const vector<int> & nbs = aResMap[ sm ];
+        subMeshEvaluated = (std::accumulate( nbs.begin(), nbs.end(), 0 ) > 0 );
+      }
+      if ( !subMeshEvaluated )
+        return false;
+    }
+    _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
+    ret = algo->Evaluate((*_father), _subShape, aResMap);
+
+    aResMap.insert( make_pair( this,vector<int>(0)));
+  }
+
+  return ret;
+}
+
+
 //=======================================================================
 /*!
  * \brief Update compute_state by _computeError and send proper events to
@@ -2129,3 +2222,29 @@ SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeS
       ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
   }
 }
+
+//================================================================================
+/*!
+ * \brief  Find common submeshes (based on shared subshapes with other
+  * \param theOther submesh to check
+  * \param theSetOfCommon set of common submesh
+ */
+//================================================================================
+
+bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
+                                     std::set<const SMESH_subMesh*>& theSetOfCommon ) const
+{
+  int oldNb = theSetOfCommon.size();
+  // check main submeshes
+  const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
+  if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
+    theSetOfCommon.insert( this );
+  if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
+    theSetOfCommon.insert( theOther );
+  // check common submeshes
+  map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
+  for( ; mapIt != _mapDepend.end(); mapIt++ )
+    if ( theOther->_mapDepend.find((*mapIt).first) != otherEnd )
+      theSetOfCommon.insert( (*mapIt).second );
+  return oldNb < theSetOfCommon.size();
+}