Salome HOME
Merge from PHASE_25_BR 09/12/2010
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 88469304d6dcdab6faa2747b553ec8ec493cfa17..a85e23e23d5e9b024ca354ae777d0c117207aa22 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
@@ -19,6 +19,7 @@
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 //  SMESH SMESH : implementaion of SMESH idl descriptions
 //  File   : SMESH_Mesh.cxx
 //  Author : Paul RASCLE, EDF
@@ -98,7 +99,9 @@ SMESH_Mesh::SMESH_Mesh(int               theLocalId,
   _myMeshDS      = theDocument->GetMesh(_idDoc);
   _isShapeToMesh = false;
   _isAutoColor   = false;
+  _isModified    = false;
   _shapeDiagonal = 0.0;
+  _rmGroupCallUp = 0;
   _myMeshDS->ShapeToMesh( PseudoShape() );
 }
 
@@ -124,6 +127,9 @@ SMESH_Mesh::~SMESH_Mesh()
     delete aGroup;
   }
   _mapGroup.clear();
+
+  if ( _rmGroupCallUp) delete _rmGroupCallUp;
+  _rmGroupCallUp = 0;
 }
 
 //=============================================================================
@@ -186,6 +192,7 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
     _shapeDiagonal = 0.0;
     _myMeshDS->ShapeToMesh( PseudoShape() );
   }
+  _isModified = false;
 }
 
 //=======================================================================
@@ -258,14 +265,14 @@ void SMESH_Mesh::Clear()
   _myMeshDS->ClearMesh();
 
   // update compute state of submeshes
-  if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) {
-    SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
-                                                             /*complexShapeFirst=*/false);
-    while ( smIt->more() ) {
-      sm = smIt->next();
-      sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
-    }
+  if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) )
+  {
+    sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918)
+    sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
   }
+  _isModified = false;
 }
 
 //=======================================================================
@@ -453,6 +460,9 @@ SMESH_Hypothesis::Hypothesis_Status
   // NotConformAllowed can be only global
   if ( !isGlobalHyp )
   {
+    // NOTE: this is not a correct way to check a name of hypothesis,
+    // there should be an attribute of hypothesis saying that it can/can't
+    // be global/local
     string hypName = anHyp->GetName();
     if ( hypName == "NotConformAllowed" )
     {
@@ -495,6 +505,7 @@ SMESH_Hypothesis::Hypothesis_Status
       }
     }
   }
+  HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
 
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
@@ -566,7 +577,9 @@ SMESH_Hypothesis::Hypothesis_Status
       }
     }
   }
-  
+
+  HasModificationsToDiscard(); // to reset _isModified flag if mesh become empty
+
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
   return ret;
@@ -963,6 +976,7 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
       }
     }
   }
+  HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
 }
 
 //=============================================================================
@@ -982,6 +996,57 @@ bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
   return _isAutoColor;
 }
 
+//=======================================================================
+//function : SetIsModified
+//purpose  : Set the flag meaning that the mesh has been edited "manually"
+//=======================================================================
+
+void SMESH_Mesh::SetIsModified(bool isModified)
+{
+  _isModified = isModified;
+
+  if ( _isModified )
+    // check if mesh becomes empty as result of modification
+    HasModificationsToDiscard();
+}
+
+//=======================================================================
+//function : HasModificationsToDiscard
+//purpose  : Return true if the mesh has been edited since a total re-compute
+//           and those modifications may prevent successful partial re-compute.
+//           As a side effect reset _isModified flag if mesh is empty
+//issue    : 0020693
+//=======================================================================
+
+bool SMESH_Mesh::HasModificationsToDiscard() const
+{
+  if ( ! _isModified )
+    return false;
+
+  // return true if there the next Compute() will be partial and
+  // existing but changed elements may prevent successful re-compute
+  bool hasComputed = false, hasNotComputed = false;
+  map <int, SMESH_subMesh*>::const_iterator i_sm = _mapSubMesh.begin();
+  for ( ; i_sm != _mapSubMesh.end() ; ++i_sm )
+    switch ( i_sm->second->GetSubShape().ShapeType() )
+    {
+    case TopAbs_EDGE:
+    case TopAbs_FACE:
+    case TopAbs_SOLID:
+      if ( i_sm->second->IsMeshComputed() )
+        hasComputed = true;
+      else
+        hasNotComputed = true;
+      if ( hasComputed && hasNotComputed)
+        return true;
+    }
+
+  if ( !hasComputed )
+    const_cast<SMESH_Mesh*>(this)->_isModified = false;
+
+  return false;
+}
+
 //=============================================================================
 /*! Export* methods.
  *  To store mesh contents on disk in different formats.
@@ -1351,6 +1416,18 @@ list<int> SMESH_Mesh::GetGroupIds() const
   return anIds;
 }
 
+//================================================================================
+/*!
+ * \brief Set a caller of RemoveGroup() at level of CORBA API implementation.
+ * The set upCaller will be deleted by SMESH_Mesh
+ */
+//================================================================================
+
+void SMESH_Mesh::SetRemoveGroupCallUp( TRmGroupCallUp* upCaller )
+{
+  if ( _rmGroupCallUp ) delete _rmGroupCallUp;
+  _rmGroupCallUp = upCaller;
+}
 
 //=============================================================================
 /*!
@@ -1358,13 +1435,16 @@ list<int> SMESH_Mesh::GetGroupIds() const
  */
 //=============================================================================
 
-void SMESH_Mesh::RemoveGroup (const int theGroupID)
+bool SMESH_Mesh::RemoveGroup (const int theGroupID)
 {
   if (_mapGroup.find(theGroupID) == _mapGroup.end())
-    return;
+    return false;
   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
   delete _mapGroup[theGroupID];
   _mapGroup.erase (theGroupID);
+  if (_rmGroupCallUp)
+    _rmGroupCallUp->RemoveGroup( theGroupID );
+  return true;
 }
 
 //=======================================================================
@@ -1553,6 +1633,7 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
     for ( desType = TopAbs_VERTEX; desType >= memberType; desType-- )
       for (TopExp_Explorer des( theShape, TopAbs_ShapeEnum( desType )); des.More(); des.Next())
       {
+        if ( !_mapAncestors.Contains( des.Current() )) continue;// issue 0020982
         TopTools_ListOfShape& ancList = _mapAncestors.ChangeFromKey( des.Current() );
         TopTools_ListIteratorOfListOfShape ancIt (ancList);
         while ( ancIt.More() && ancIt.Value().ShapeType() >= memberType )