Salome HOME
23413: [CEA 2025] bug SMESH orientation
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 13747255c7afff32fca9f70317b74800fa29c528..eac04a4d1604fda010e7e467e0897f81f132a8b7 100644 (file)
@@ -438,6 +438,7 @@ void SMESH_Mesh::Clear()
       sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
     }
   }
+  GetMeshDS()->Modified();
   _isModified = false;
 }
 
@@ -713,6 +714,7 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
     }
   }
   HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
+  GetMeshDS()->Modified();
 
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
@@ -783,6 +785,7 @@ SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
   }
 
   HasModificationsToDiscard(); // to reset _isModified flag if mesh become empty
+  GetMeshDS()->Modified();
 
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
@@ -1208,49 +1211,67 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   SMESH_Algo *algo;
   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;
+  bool allMeshedEdgesNotified = true;
 
   SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   while ( smIt->more() )
   {
     SMESH_subMesh* aSubMesh = smIt->next();
+    bool toNotify = false;
 
     // if aSubMesh meshing depends on hyp,
     // we call aSubMesh->AlgoStateEngine( MODIF_HYP, hyp ) that causes either
     // 1) clearing already computed aSubMesh or
     // 2) changing algo_state from MISSING_HYP to HYP_OK when parameters of hyp becomes valid,
     // 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 &&
-         !hyp->DataDependOnParams() )
-      continue;
-
-    const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
-
-    if (( aSubMesh->IsApplicableHypotesis( hyp )) &&
-        ( algo = aSubMesh->GetAlgo() )            &&
-        ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
-        ( compatibleHypoKind->IsOk( hyp, aSubShape )))
+    if ( aSubMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK ||
+         aSubMesh->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE ||
+         aSubMesh->GetAlgoState()    == SMESH_subMesh::MISSING_HYP ||
+         hyp->DataDependOnParams() )
     {
-      // check if hyp is used by algo
-      usedHyps.clear();
-      if ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
-           find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
+      const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
+
+      if (( aSubMesh->IsApplicableHypotesis( hyp )) &&
+          ( algo = aSubMesh->GetAlgo() )            &&
+          ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
+          ( compatibleHypoKind->IsOk( hyp, aSubShape )))
       {
-        smToNotify.push_back( aSubMesh );
+        // check if hyp is used by algo
+        usedHyps.clear();
+        toNotify = ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
+                     std::find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() );
       }
     }
+    if ( toNotify )
+    {
+      smToNotify.push_back( aSubMesh );
+      if ( aSubMesh->GetAlgoState() == SMESH_subMesh::MISSING_HYP )
+        allMeshedEdgesNotified = false; //  update of algo state needed, not mesh clearing
+    }
+    else
+    {
+      if ( !aSubMesh->IsEmpty() &&
+           aSubMesh->GetSubShape().ShapeType() == TopAbs_EDGE )
+        allMeshedEdgesNotified = false;
+    }
   }
+  if ( smToNotify.empty() )
+    return;
 
-  for ( size_t i = 0; i < smToNotify.size(); ++i )
+  // if all meshed EDGEs will be notified then the notification is equivalent
+  // to the whole mesh clearing, which is usually faster
+  if ( allMeshedEdgesNotified && NbNodes() > 0 )
   {
-    smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
-                                   const_cast< SMESH_Hypothesis*>( hyp ));
+    Clear();
+  }
+  else
+  {
+    // notify in reverse order to avoid filling the pool of IDs
+    for ( int i = smToNotify.size()-1; i >= 0; --i )
+      smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
+                                     const_cast< SMESH_Hypothesis*>( hyp ));
   }
-
   HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
   GetMeshDS()->Modified();
 }
@@ -1365,6 +1386,8 @@ bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
      *         - 2D if all mesh nodes lie on XOY coordinate plane, or
      *         - 3D in the rest cases.
      *         If \a theAutoDimension is \c false, the space dimension is always 3.
+ *  \param [in] theAddODOnVertices - to create 0D elements on all vertices
+ *  \param [in] theAllElemsToGroup - to make every element to belong to any group (PAL23413)
  *  \return int - mesh index in the file
  */
 //================================================================================
@@ -1375,7 +1398,8 @@ void SMESH_Mesh::ExportMED(const char *        file,
                            int                 theVersion,
                            const SMESHDS_Mesh* meshPart,
                            bool                theAutoDimension,
-                           bool                theAddODOnVertices)
+                           bool                theAddODOnVertices,
+                           bool                theAllElemsToGroup)
   throw(SALOME_Exception)
 {
   SMESH_TRY;
@@ -1398,6 +1422,8 @@ void SMESH_Mesh::ExportMED(const char *        file,
     myWriter.AddGroupOfFaces();
     myWriter.AddGroupOfVolumes();
   }
+  if ( theAllElemsToGroup )
+    myWriter.AddAllToGroup();
 
   // Pass groups to writer. Provide unique group names.
   //set<string> aGroupNames; // Corrected for Mantis issue 0020028
@@ -1453,7 +1479,9 @@ void SMESH_Mesh::ExportSAUV(const char *file,
   cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
   cmd += "\"";
   system(cmd.c_str());
-  ExportMED(medfilename.c_str(), theMeshName, theAutoGroups, 1);
+  ExportMED(medfilename.c_str(), theMeshName, theAutoGroups, /*theVersion=*/1,
+            /*meshPart=*/NULL, /*theAutoDimension=*/false, /*theAddODOnVertices=*/false,
+            /*theAllElemsToGroup=*/true ); // theAllElemsToGroup is for PAL0023413
 #ifdef WIN32
   cmd = "%PYTHONBIN% ";
 #else
@@ -1604,7 +1632,7 @@ double SMESH_Mesh::GetComputeProgress() const
       const std::vector<SMESH_subMesh*>& smToCompute = algo->SubMeshesToCompute();
       for ( size_t i = 0; i < smToCompute.size(); ++i )
       {
-        if ( smToCompute[i]->IsEmpty() )
+        if ( smToCompute[i]->IsEmpty() || smToCompute.size() == 1 )
           algoNotDoneCost += smToCompute[i]->GetComputeCost();
         else
           algoDoneCost += smToCompute[i]->GetComputeCost();
@@ -2349,7 +2377,7 @@ bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) con
   vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
   vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
 
-  // iterate on ordered submeshes and insert them in detected positions
+  // iterate on ordered sub-meshes and insert them in detected positions
   map< int, TPosInList >::iterator i_pos = sortedPos.begin();
   for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
     *(i_pos->second) = *onlyBIt;
@@ -2367,18 +2395,27 @@ bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore,
                             const SMESH_subMesh* smAfter ) const
 {
   TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin();
-  TListOfInt::const_iterator idBef, idAft;
   for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++)
   {
     const TListOfInt& listOfId = *listIdsIt;
-    idBef = std::find( listOfId.begin(), listOfId.end(), smBefore->GetId() );
-    if ( idBef != listOfId.end() )
-      idAft = std::find( listOfId.begin(), listOfId.end(), smAfter->GetId() );
-    if ( idAft != listOfId.end () )
-      return ( std::distance( listOfId.begin(), idBef ) <
-               std::distance( listOfId.begin(), idAft )   );
+    int iB = -1, iA = -1, i = 0;
+    for ( TListOfInt::const_iterator id = listOfId.begin(); id != listOfId.end(); ++id, ++i )
+    {
+      if ( *id == smBefore->GetId() )
+      {
+        iB = i;
+        if ( iA > -1 )
+          return iB < iA;
+      }
+      else if ( *id == smAfter->GetId() )
+      {
+        iA = i;
+        if ( iB > -1 )
+          return iB < iA;
+      }
+    }
   }
-  return true; // no order imposed to given submeshes
+  return true; // no order imposed to given sub-meshes
 } 
 
 //=============================================================================