Salome HOME
0022238: Study dump produced by SMESH refers to undefined variable names
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
index 05e266c386252ed71fcaa1aefd39d892aadaf8d0..f42b7a476068802ad920e45fd411da02409dc8db 100644 (file)
 //
 #include "SMESH_2smeshpy.hxx"
 
-#include "utilities.h"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_NoteBook.hxx"
 #include "SMESH_Filter_i.hxx"
 
+#include <utilities.h>
+
 #include <Resource_DataMapOfAsciiStringAsciiString.hxx>
 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
 
@@ -177,7 +178,33 @@ namespace {
 
   void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects)
   {
-    for ( int iArg = cmd->GetNbArgs(); iArg; --iArg )
+    // either comment or erase a command including NotPublishedObjectName()
+    if ( cmd->GetString().Location( TPythonDump::NotPublishedObjectName(), 1, cmd->Length() ))
+    {
+      bool isResultPublished = false;
+      for ( int i = 0; i < cmd->GetNbResultValues(); i++ )
+      {
+        _pyID objID = cmd->GetResultValue( i+1 );
+        if ( cmd->IsStudyEntry( objID ))
+          isResultPublished = (! theGen->IsNotPublished( objID ));
+        theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed
+      }
+      if ( isResultPublished )
+        cmd->Comment();
+      else
+        cmd->Clear();
+      return;
+    }
+    // check if an Object was created in the script
+    _AString comment;
+    const _pyID& obj = cmd->GetObject();
+    if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
+    {
+      comment = "not created Object";
+      theGen->ObjectCreationRemoved( obj );
+    }
+    // check if a command has not created args
+    for ( int iArg = cmd->GetNbArgs(); iArg && comment.IsEmpty(); --iArg )
     {
       const _pyID& arg = cmd->GetArg( iArg );
       if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' )
@@ -187,25 +214,29 @@ namespace {
       for ( ; id != idList.end(); ++id )
         if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id ))
         {
-          cmd->Comment();
-          cmd->GetString() += " ### " ;
-          cmd->GetString() += *id + " has not been yet created";
-          return;
+          comment += *id + " has not been yet created";
+          break;
         }
     }
-    const _pyID& obj = cmd->GetObject();
-    if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
+    // treat result objects
+    const _pyID& result = cmd->GetResultValue();
+    if ( !result.IsEmpty() && result.Value( 1 ) != '"' && result.Value( 1 ) != '\'' )
+    {
+      list< _pyID > idList = cmd->GetStudyEntries( result );
+      list< _pyID >::iterator id = idList.begin();
+      for ( ; id != idList.end(); ++id )
+        if ( comment.IsEmpty() )
+          presentObjects.insert( *id );
+        else
+          theGen->ObjectCreationRemoved( *id ); // objID.SetName( name ) is not needed
+    }
+    // comment the command
+    if ( !comment.IsEmpty() )
     {
       cmd->Comment();
-      cmd->GetString() += " ### not created object" ;
+      cmd->GetString() += " ### ";
+      cmd->GetString() += comment;
     }
-    const _pyID& result = cmd->GetResultValue();
-    if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' )
-      return;
-    list< _pyID > idList = cmd->GetStudyEntries( result );
-    list< _pyID >::iterator id = idList.begin();
-    for ( ; id != idList.end(); ++id )
-      presentObjects.insert( *id );
   }
 
   //================================================================================
@@ -254,6 +285,8 @@ namespace {
     //   - FT_EqualVolumes          = 17
     // v 6.6.0: FT_Undefined == 44, new items:
     //   - FT_BallDiameter          = 37
+    // v 6.7.1: FT_Undefined == 45, new items:
+    //   - FT_EntityType            = 36
     //
     // It's necessary to continue recording this history and to fill
     // undef2newItems (see below) accordingly.
@@ -273,6 +306,9 @@ namespace {
         undef2newItems[ 43 ].assign( items, items+4 ); }
       { int items[] = { 37 };
         undef2newItems[ 44 ].assign( items, items+1 ); }
+      // { int items[] = { 36 };
+      //undef2newItems[ 45 ].assign( items, items+1 ); }
+      ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined );
     }
 
     int iType     = Type.IntegerValue();
@@ -312,13 +348,15 @@ namespace {
 
 //================================================================================
 /*!
- * \brief Convert python script using commands of smesh.py
-  * \param theScript - Input script
-  * \retval TCollection_AsciiString - Convertion result
-  * \param theToKeepAllCommands - to keep all commands or
-  *        to exclude commands relating to objects removed from study
-  *
-  * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx
+ * \brief Convert a python script using commands of smesh.py
+ *  \param theScript - Input script
+ *  \param theEntry2AccessorMethod - returns method names to access to
+ *         objects wrapped with python class
+ *  \param theObjectNames - names of objects
+ *  \param theRemovedObjIDs - entries of objects whose created commands were removed
+ *  \param theHistoricalDump - true means to keep all commands, false means
+ *         to exclude commands relating to objects removed from study
+ *  \retval TCollection_AsciiString - Convertion result
  */
 //================================================================================
 
@@ -326,10 +364,15 @@ TCollection_AsciiString
 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScript,
                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
                               Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
+                              std::set< TCollection_AsciiString >&      theRemovedObjIDs,
                               SALOMEDS::Study_ptr&                      theStudy,
                               const bool                                theToKeepAllCommands)
 {
-  theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands );
+  theGen = new _pyGen( theEntry2AccessorMethod,
+                       theObjectNames,
+                       theRemovedObjIDs,
+                       theStudy,
+                       theToKeepAllCommands );
 
   // split theScript into separate commands
 
@@ -339,9 +382,9 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScrip
   while ( from < end && ( to = theScript.Location( "\n", from, end )))
   {
     if ( to != from )
-        // cut out and store a command
-        aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
-      from = to + 1;
+      // cut out and store a command
+      aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
+    from = to + 1;
   }
 
   aNoteBook->ReplaceVariables();
@@ -410,12 +453,14 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScrip
 
 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
                Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
+               std::set< TCollection_AsciiString >&      theRemovedObjIDs,
                SALOMEDS::Study_ptr&                      theStudy,
                const bool                                theToKeepAllCommands)
   : _pyObject( new _pyCommand( "", 0 )),
     myNbCommands( 0 ),
     myID2AccessorMethod( theEntry2AccessorMethod ),
     myObjectNames( theObjectNames ),
+    myRemovedObjIDs( theRemovedObjIDs ),
     myNbFilters( 0 ),
     myToKeepAllCommands( theToKeepAllCommands ),
     myStudy( SALOMEDS::Study::_duplicate( theStudy )),
@@ -658,7 +703,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand
     // 1    2       3         4            5           6       7        8         9             10
     // in order to avoid the problem of type mismatch of long and FunctorType
     const TCollection_AsciiString
-      SMESH("SMESH."), dfltFunctor = "SMESH.FT_Undefined", dftlTol = "1e-07", dftlPreci = "-1";
+      SMESH("SMESH."), dfltFunctor("SMESH.FT_Undefined"), dftlTol("1e-07"), dftlPreci("-1");
     TCollection_AsciiString
       Type          = aCommand->GetArg(1),  // long
       Compare       = aCommand->GetArg(2),  // long
@@ -684,17 +729,34 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand
     aCommand->SetArg( 2, Type );
     aCommand->SetArg( 3, Compare );
 
-    if ( Type == "SMESH.FT_ElemGeomType" && Threshold.IsIntegerValue() )
+    if ( Threshold.IsIntegerValue() )
     {
-      // set SMESH.GeometryType instead of a numerical Threshold
-      const char* types[SMESH::Geom_BALL+1] = {
-        "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON",
-        "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM",
-        "Geom_POLYHEDRA", "Geom_BALL"
-      };
       int iGeom = Threshold.IntegerValue();
-      if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 )
-        Threshold = SMESH + types[ iGeom ];
+      if ( Type == "SMESH.FT_ElemGeomType" )
+      {
+        // set SMESH.GeometryType instead of a numerical Threshold
+        const char* types[SMESH::Geom_BALL+1] = {
+          "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON",
+          "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM",
+          "Geom_POLYHEDRA", "Geom_BALL" };
+        if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 )
+          Threshold = SMESH + types[ iGeom ];
+      }
+      if (Type == "SMESH.FT_EntityType")
+      {
+        // set SMESH.EntityType instead of a numerical Threshold
+        const char* types[SMESH::Entity_Ball+1] = {
+          "Entity_Node", "Entity_0D", "Entity_Edge", "Entity_Quad_Edge",
+          "Entity_Triangle", "Entity_Quad_Triangle",
+          "Entity_Quadrangle", "Entity_Quad_Quadrangle", "Entity_BiQuad_Quadrangle",
+          "Entity_Polygon", "Entity_Quad_Polygon", "Entity_Tetra", "Entity_Quad_Tetra",
+          "Entity_Pyramid", "Entity_Quad_Pyramid",
+          "Entity_Hexa", "Entity_Quad_Hexa", "Entity_TriQuad_Hexa",
+          "Entity_Penta", "Entity_Quad_Penta", "Entity_Hexagonal_Prism",
+          "Entity_Polyhedra", "Entity_Quad_Polyhedra", "Entity_Ball" };
+        if ( -1 < iGeom && iGeom < SMESH::Entity_Quad_Polyhedra+1 )
+          Threshold = SMESH + types[ iGeom ];
+      }
     }
     if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or ""
       aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry
@@ -764,13 +826,21 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand )
       method == "CreateMeshesFromSAUV"||
       method == "CreateMeshesFromGMF" )
   {
-    for(int ind = 0;ind<theCommand->GetNbResultValues();ind++)
+    for ( int ind = 0; ind < theCommand->GetNbResultValues(); ind++ )
     {
       _pyID meshID = theCommand->GetResultValue(ind+1);
       if ( !theCommand->IsStudyEntry( meshID ) ) continue;
       Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1));
       myMeshes.insert( make_pair( mesh->GetID(), mesh ));
     }
+    if ( method == "CreateMeshesFromGMF" )
+    {
+      // CreateMeshesFromGMF( theFileName, theMakeRequiredGroups ) ->
+      // CreateMeshesFromGMF( theFileName )
+      _AString file = theCommand->GetArg(1);
+      theCommand->RemoveArgs();
+      theCommand->SetArg( 1, file );
+    }
   }
 
   // CreateHypothesis()
@@ -818,7 +888,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand )
     }
   }
 
-  // objects erasing creation command if no more it's commands invoked:
+  // objects erasing creation command if no more its commands invoked:
   // SMESH_Pattern, FilterManager
   if ( method == "GetPattern" ||
        method == "CreateFilterManager" ||
@@ -1337,6 +1407,19 @@ bool _pyGen::IsNotPublished(const _pyID& theObjID) const
   return true; // SMESH object not in study
 }
 
+//================================================================================
+/*!
+ * \brief Remove object name from myObjectNames that leads to that SetName() for
+ *        this object is not dumped
+ *  \param [in] theObjID - entry of the object whose creation command was eliminated
+ */
+//================================================================================
+
+void _pyGen::ObjectCreationRemoved(const _pyID& theObjID)
+{
+  myRemovedObjIDs.insert( theObjID );
+}
+
 //================================================================================
 /*!
  * \brief Return reader of  hypotheses of plugins
@@ -1569,7 +1652,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
          method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED()
       theCommand->SetMethod( "ExportMED" );
     }
-    else if ( method == "ExportCGNS" || method == "ExportGMF" )
+    else if ( method == "ExportCGNS" )
     { // ExportCGNS(part, ...) -> ExportCGNS(..., part)
       _pyID partID = theCommand->GetArg( 1 );
       int nbArgs = theCommand->GetNbArgs();
@@ -1577,6 +1660,14 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
         theCommand->SetArg( i-1, theCommand->GetArg( i ));
       theCommand->SetArg( nbArgs, partID );
     }
+    else if ( method == "ExportGMF" )
+    { // ExportGMF(part,file,bool) -> ExportCGNS(file, part)
+      _pyID partID  = theCommand->GetArg( 1 );
+      _AString file = theCommand->GetArg( 2 );
+      theCommand->RemoveArgs();
+      theCommand->SetArg( 1, file );
+      theCommand->SetArg( 2, partID );
+    }
     else if ( theCommand->MethodStartsFrom( "ExportPartTo" ))
     { // ExportPartTo*(part, ...) -> Export*(..., part)
       //
@@ -1978,7 +2069,8 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
     const char * names[] = {
       "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall",
       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint",
-      "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject",
+      "InverseDiag","DeleteDiag","Reorient","ReorientObject",
+      "TriToQuad","TriToQuadObject", "SplitQuad","SplitQuadObject",
       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
       "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D",
@@ -2032,6 +2124,13 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
     if (( isPyMeshMethod = ( newMethod.Length() > 0 )))
       theCommand->SetMethod( newMethod );
   }
+  // ConvertToBiQuadratic(...) -> ConvertToQuadratic(...,True)
+  if ( !isPyMeshMethod && (method == "ConvertToBiQuadratic" || method == "ConvertToBiQuadraticObject") )
+  {
+    isPyMeshMethod = true;
+    theCommand->SetMethod( method.SubString( 1, 9) + method.SubString( 12, method.Length()));
+    theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" );
+  }
 
   if ( !isPyMeshMethod )
   {
@@ -2127,15 +2226,13 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
       theCommand->SetArg( 3, face );
   }
 
-  if(method == "QuadToTri" || method == "QuadToTriObject")\r
-  {\r
-    int crit_arg = theCommand->GetNbArgs();\r
-    _AString crit = theCommand->GetArg(crit_arg);\r
-    if(crit.Search("MaxElementLength2D") != -1)\r
-    {\r
-      theCommand->SetArg(crit_arg, "");\r
-      isPyMeshMethod = true;\r
-    }\r
+  if ( method == "QuadToTri" || method == "QuadToTriObject" )
+  {
+    isPyMeshMethod = true;
+    int crit_arg = theCommand->GetNbArgs();
+    const _AString& crit = theCommand->GetArg(crit_arg);
+    if (crit.Search("MaxElementLength2D") != -1)
+      theCommand->SetArg(crit_arg, "");
   }
 
   if ( isPyMeshMethod )
@@ -3072,6 +3169,7 @@ int _pyCommand::GetBegPos( int thePartIndex )
     return EMPTY;
   if ( myBegPos.Length() < thePartIndex )
     return UNKNOWN;
+  ASSERT( thePartIndex > 0 );
   return myBegPos( thePartIndex );
 }
 
@@ -3087,6 +3185,7 @@ void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
 {
   while ( myBegPos.Length() < thePartIndex )
     myBegPos.Append( UNKNOWN );
+  ASSERT( thePartIndex > 0 );
   myBegPos( thePartIndex ) = thePosition;
 }
 
@@ -3139,22 +3238,21 @@ const TCollection_AsciiString & _pyCommand::GetResultValue()
 //================================================================================
 /*!
  * \brief Return number of python command result value ResultValue = Obj.Meth()
-  * \retval const int
  */
 //================================================================================
 
-const int _pyCommand::GetNbResultValues()
+int _pyCommand::GetNbResultValues()
 {
+  int nb     = 0;
   int begPos = 1;
-  int Nb=0;
   int endPos = myString.Location( "=", 1, Length() );
-  TCollection_AsciiString str = "";
-  while ( begPos < endPos) {
-    str = GetWord( myString, begPos, true );
+  while ( begPos < endPos )
+  {
+    _AString str = GetWord( myString, begPos, true );
     begPos = begPos+ str.Length();
-    Nb++;
+    nb++;
   }
-  return (Nb-1);
+  return (nb-1);
 }
 
 
@@ -3592,7 +3690,7 @@ void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
 
 void _pyCommand::RemoveArgs()
 {
-  if ( int pos = myString.Location( '(', 1, Length() ))
+  if ( int pos = myString.Location( '(', Max( 1, GetBegPos( METHOD_IND )), Length() ))
     myString.Trunc( pos );
   myString += ")";
   myArgs.Clear();
@@ -3615,7 +3713,7 @@ void _pyCommand::Comment()
   if ( i <= Length() )
   {
     myString.Insert( i, "#" );
-    for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart )
+    for ( int iPart = 1; iPart <= myBegPos.Length(); ++iPart )
     {
       int begPos = GetBegPos( iPart );
       if ( begPos != UNKNOWN )