Salome HOME
Copyright update: 2016
[modules/smesh.git] / src / SMESH / SMESH_Gen.cxx
index c8ba34bc33dc1d07aa213dab65459e05aeb88408..217806cd104384efec8584d6f93cdbc8eaabb823 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
@@ -70,9 +70,7 @@ SMESH_Gen::SMESH_Gen()
   _segmentation = _nbSegments = 10;
   SMDS_Mesh::_meshList.clear();
   MESSAGE(SMDS_Mesh::_meshList.size());
-  //_counters = new counters(100);
   _compute_canceled = false;
-  _sm_current = NULL;
   //vtkDebugLeaks::SetExitError(0);
 }
 
@@ -182,9 +180,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       {
         if (_compute_canceled)
           return false;
-        _sm_current = smToCompute;
+        setCurrentSubMesh( smToCompute );
         smToCompute->ComputeStateEngine( computeEvent );
-        _sm_current = NULL;
+        setCurrentSubMesh( NULL );
       }
 
       // we check all the sub-meshes here and detect if any of them failed to compute
@@ -232,7 +230,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       if ( aShapesId && aShapeDim > (int)aDim )
         continue;
 
-      SMESH_Algo* algo = GetAlgo( aMesh, aSubShape, &algoShape );
+      SMESH_Algo* algo = GetAlgo( smToCompute, &algoShape );
       if ( algo && !algo->NeedDiscreteBoundary() )
       {
         if ( algo->SupportSubmeshes() )
@@ -269,9 +267,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
         {
           if (_compute_canceled)
             return false;
-          _sm_current = smToCompute;
+          setCurrentSubMesh( smToCompute );
           smToCompute->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( smToCompute->GetId() );
         }
@@ -288,27 +286,27 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     // Apply all-dimensional algorithms supporing sub-meshes
     // ======================================================
 
+    std::vector< SMESH_subMesh* > smVec;
     for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim )
     {
       // ------------------------------------------------
       // sort list of sub-meshes according to mesh order
       // ------------------------------------------------
-      aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes[ aShapeDim ] );
+      smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(),
+                    smWithAlgoSupportingSubmeshes[ aShapeDim ].end() );
+      aMesh.SortByMeshOrder( smVec );
 
       // ------------------------------------------------------------
       // compute sub-meshes with local uni-dimensional algos under
       // sub-meshes with all-dimensional algos
       // ------------------------------------------------------------
-      list< SMESH_subMesh* >::iterator subIt, subEnd;
-      subIt  = smWithAlgoSupportingSubmeshes[ aShapeDim ].begin();
-      subEnd = smWithAlgoSupportingSubmeshes[ aShapeDim ].end();
       // start from lower shapes
-      for ( ; subIt != subEnd; ++subIt )
+      for ( size_t i = 0; i < smVec.size(); ++i )
       {
-        sm = *subIt;
+        sm = smVec[i];
 
         // get a shape the algo is assigned to
-        if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
+        if ( !GetAlgo( sm, & algoShape ))
           continue; // strange...
 
         // look for more local algos
@@ -331,7 +329,8 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
             .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
             .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
 
-          if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
+          if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
+          {
             if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
             SMESH_Hypothesis::Hypothesis_Status status;
             if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
@@ -343,10 +342,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       // --------------------------------
       // apply the all-dimensional algos
       // --------------------------------
-      subIt  = smWithAlgoSupportingSubmeshes[ aShapeDim ].begin();
-      for ( ; subIt != subEnd; ++subIt )
+      for ( size_t i = 0; i < smVec.size(); ++i )
       {
-        sm = *subIt;
+        sm = smVec[i];
         if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
         {
           const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
@@ -356,9 +354,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
           if (_compute_canceled)
             return false;
-          _sm_current = sm;
+          setCurrentSubMesh( sm );
           sm->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( sm->GetId() );
         }
@@ -401,8 +399,9 @@ void SMESH_Gen::PrepareCompute(SMESH_Mesh &          aMesh,
                                const TopoDS_Shape &  aShape)
 {
   _compute_canceled = false;
-  _sm_current = NULL;
+  resetCurrentSubMesh();
 }
+
 //=============================================================================
 /*!
  * Cancel Compute a mesh
@@ -412,10 +411,44 @@ void SMESH_Gen::CancelCompute(SMESH_Mesh &          aMesh,
                               const TopoDS_Shape &  aShape)
 {
   _compute_canceled = true;
-  if(_sm_current)
-    {
-      _sm_current->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
-    }
+  if ( const SMESH_subMesh* sm = GetCurrentSubMesh() )
+  {
+    const_cast< SMESH_subMesh* >( sm )->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
+  }
+  resetCurrentSubMesh();
+}
+
+//================================================================================
+/*!
+ * \brief Returns a sub-mesh being currently computed
+ */
+//================================================================================
+
+const SMESH_subMesh* SMESH_Gen::GetCurrentSubMesh() const
+{
+  return _sm_current.empty() ? 0 : _sm_current.back();
+}
+
+//================================================================================
+/*!
+ * \brief Sets a sub-mesh being currently computed.
+ *
+ * An algorithm can call Compute() for a sub-shape, hence we keep a stack of sub-meshes
+ */
+//================================================================================
+
+void SMESH_Gen::setCurrentSubMesh(SMESH_subMesh* sm)
+{
+  if ( sm )
+    _sm_current.push_back( sm );
+
+  else if ( !_sm_current.empty() )
+    _sm_current.pop_back();
+}
+
+void SMESH_Gen::resetCurrentSubMesh()
+{
+  _sm_current.clear();
 }
 
 //=============================================================================
@@ -478,7 +511,7 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
       const int aShapeDim = GetShapeDim( aSubShape );
       if ( aShapeDim < 1 ) break;
       
-      SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
+      SMESH_Algo* algo = GetAlgo( smToCompute );
       if ( algo && !algo->NeedDiscreteBoundary() ) {
         if ( algo->SupportSubmeshes() ) {
           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
@@ -494,22 +527,22 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
     // ------------------------------------------------------------
     // sort list of meshes according to mesh order
     // ------------------------------------------------------------
-    aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
+    std::vector< SMESH_subMesh* > smVec( smWithAlgoSupportingSubmeshes.begin(),
+                                         smWithAlgoSupportingSubmeshes.end() );
+    aMesh.SortByMeshOrder( smVec );
 
     // ------------------------------------------------------------
     // compute sub-meshes under shapes with algos that DO NOT require
     // Discreteized boundaries and DO support sub-meshes
     // ------------------------------------------------------------
-    list< SMESH_subMesh* >::iterator subIt, subEnd;
-    subIt  = smWithAlgoSupportingSubmeshes.begin();
-    subEnd = smWithAlgoSupportingSubmeshes.end();
     // start from lower shapes
-    for ( ; subIt != subEnd; ++subIt ) {
-      sm = *subIt;
+    for ( size_t i = 0; i < smVec.size(); ++i )
+    {
+      sm = smVec[i];
 
       // get a shape the algo is assigned to
       TopoDS_Shape algoShape;
-      if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
+      if ( !GetAlgo( sm, & algoShape ))
         continue; // strange...
 
       // look for more local algos
@@ -526,7 +559,8 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
 
-        if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
+        if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true ))
+        {
           if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
           SMESH_Hypothesis::Hypothesis_Status status;
           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
@@ -538,9 +572,9 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
     // ----------------------------------------------------------
     // apply the algos that do not require Discreteized boundaries
     // ----------------------------------------------------------
-    for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
+    for ( size_t i = 0; i < smVec.size(); ++i )
     {
-      sm = *subIt;
+      sm = smVec[i];
       sm->Evaluate(aResMap);
       if ( aShapesId )
         aShapesId->insert( sm->GetId() );
@@ -910,7 +944,7 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
   if ( !hasAlgo ) {
     ret = false;
     theErrors.push_back( TAlgoStateError() );
-    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true );
+    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, theMesh.HasShapeToMesh() ? 1 : 3, true );
   }
 
   return ret;
@@ -1014,6 +1048,23 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
                                const TopoDS_Shape & aShape,
                                TopoDS_Shape*        assignedTo)
 {
+  return GetAlgo( aMesh.GetSubMesh( aShape ), assignedTo );
+}
+
+//=============================================================================
+/*!
+ * Finds algo to mesh a sub-mesh. Optionally returns a shape the found algo is bound to
+ */
+//=============================================================================
+
+SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_subMesh * aSubMesh,
+                               TopoDS_Shape*   assignedTo)
+{
+  if ( !aSubMesh ) return 0;
+
+  const TopoDS_Shape & aShape = aSubMesh->GetSubShape();
+  SMESH_Mesh&          aMesh  = *aSubMesh->GetFather();
+
   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
   filter.And( filter.IsApplicableTo( aShape ));
 
@@ -1021,7 +1072,7 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
 
   TopoDS_Shape assignedToShape;
   SMESH_Algo* algo =
-    (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape );
+    (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape );
 
   if ( algo &&
        aShape.ShapeType() == TopAbs_FACE &&
@@ -1036,7 +1087,7 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
     filter.AndNot( filter.Is( algo ));
     TopoDS_Shape assignedToShape2;
     SMESH_Algo* algo2 =
-      (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, &assignedToShape2 );
+      (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape2 );
     if ( algo2 &&                                                  // algo found
          !assignedToShape2.IsSame( aMesh.GetShapeToMesh() ) &&     // algo is local
          ( SMESH_MesherHelper::GetGroupType( assignedToShape2 ) == // algo of the same level