]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
Merge C++ part of kleontev/38044_auto_repair
authorNATHALIE GORE <ng13417n@dsp1077169.postes.calibre.edf.fr>
Thu, 4 Apr 2024 09:49:08 +0000 (11:49 +0200)
committerNabil Ghodbane <nabil.ghodbane@cea.fr>
Mon, 8 Apr 2024 08:21:32 +0000 (10:21 +0200)
14 files changed:
idl/GEOM_Gen.idl
src/GEOM/GEOM_Engine.cxx
src/GEOMGUI/GeometryGUI.cxx
src/GEOMImpl/GEOMImpl_IHealingOperations.cxx
src/GEOMImpl/GEOMImpl_IHealingOperations.hxx
src/GEOMImpl/GEOMImpl_Types.hxx
src/GEOM_I/GEOM_IHealingOperations_i.cc
src/GEOM_I/GEOM_IHealingOperations_i.hh
src/GEOM_SWIG/geomBuilder.py
src/GEOM_SWIG_WITHIHM/GEOM_Swig_LocalSelector.cxx
src/GEOM_SWIG_WITHIHM/GEOM_Swig_LocalSelector.h
src/GEOM_SWIG_WITHIHM/libGEOM_Swig.cxx
src/GEOM_SWIG_WITHIHM/libGEOM_Swig.h
src/GEOM_SWIG_WITHIHM/libGEOM_Swig.i

index b177871d9c8764bd7c3e1db09f199cd5837a3317..f81c92cee371cc165ef97bd7dfa27d3e7359fcd2 100644 (file)
@@ -4292,6 +4292,16 @@ module GEOM
      */
     GEOM_Object LimitTolerance (in GEOM_Object theObject, in double theTolerance);
 
+    /*!
+     *  \brief Provides Python dump functionality for algorithms entirely implemented in Python.
+     *  \param theObject Shape to be processed.
+     *  \param result Shape of the algorithm execution.
+     *  \param imports module import for current functon.
+     *  \param funcName name of a Python function that we need to put into dump.
+     *  \param args arguments of the Python function.
+     */
+    void FuncToPythonDump(in GEOM_Object theObject, in GEOM_Object result, in string imports, in string funcName, in string args);
+
 
     /*!
      *  \brief Return information on what has been done by the last called healing method.
index a526f9f973697afff126ee201608e5bbadcd229f..13aea9601b606aade95657920fd67df2db75b5ff 100644 (file)
@@ -152,6 +152,124 @@ static TCollection_AsciiString GetPublishCommands
 
 void Prettify(TCollection_AsciiString& theScript);
 
+// Helper functions
+namespace
+{
+  // Specifies a way to process a given function
+  enum FunctionProcessType { NOT_PROCESS, TO_PROCESS, UPDATE_DESCRIPTION };
+
+  // Starting string for an edge case where function was dumped from Python code
+  const Standard_CString funcFromPythonStartString = "from salome.geom.geomrepairadv";
+
+
+  //================================================================================
+  /*!
+  * \brief Checks if a description contents a function that was dumped from Python code
+  */
+  //================================================================================
+  bool IsFunctionSetFromPython(const TCollection_AsciiString& aDescr)
+  {
+    // TODO: make it more generic and not depended on geomrepairadv name
+    return aDescr.Search(funcFromPythonStartString) != -1;
+  }
+
+
+  //================================================================================
+  /*!
+  * \brief Removes from description the part before specific import statement
+  */
+  //================================================================================
+  void UpdateFuncFromPythonDescription(TCollection_AsciiString& aDescr)
+  {
+    const Standard_Integer startStringPos = aDescr.Search(funcFromPythonStartString);
+    MESSAGE("Description should start from pos: " << startStringPos);
+    if (startStringPos == -1)
+    {
+      MESSAGE("Can't find a string:\n" << funcFromPythonStartString << " \nin func description!");
+      return;
+    }
+
+    // Remove everything from the beginning till the starting point.
+    // Index starts from 1 not 0!
+    aDescr.Remove(1, startStringPos - 1);
+    MESSAGE("Updated func description: " << aDescr);
+  }
+
+
+  //================================================================================
+  /*!
+  * \brief Finds out how we should process a given function for Python dump
+  */
+  //================================================================================
+  FunctionProcessType GetFunctionProcessingType(const Handle(GEOM_Function)& theFunction, const TDF_LabelMap& theProcessed, const TCollection_AsciiString& aDescr)
+  {
+    MESSAGE("Start check function dependencies...");
+
+    TDF_LabelSequence aSeq;
+    theFunction->GetDependency(aSeq);
+    const Standard_Integer aLen = aSeq.Length();
+
+    for (Standard_Integer i = 1; i <= aLen; i++) {
+      TDF_Label aRefLabel = aSeq.Value(i);
+      Handle(TDF_Reference) aRef;
+      if (!aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
+        MESSAGE("Can't find TDF_Reference::GetID() attribute. Do not process.");
+        return NOT_PROCESS;
+      }
+
+      if (aRef.IsNull() || aRef->Get().IsNull()) {
+        MESSAGE("Reference to attribute is null. Do not process.");
+        return NOT_PROCESS;
+      }
+
+      Handle(TDataStd_TreeNode) aT;
+      if (!TDataStd_TreeNode::Find(aRef->Get(), aT)) {
+        MESSAGE("Can't find a tree node. Do not process.");
+        return NOT_PROCESS;
+      }
+
+      TDF_Label aDepLabel = aT->Label();
+      Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aDepLabel);
+      if (aFunction.IsNull()) {
+        MESSAGE("Function is null. Do not process." << aFunction->GetDescription());
+        return NOT_PROCESS;
+      }
+
+      if (!theProcessed.Contains(aDepLabel)) {
+        // Special case for function dumped from Python, because it's appended to
+        // description of other function that should be rejected early.
+        // TODO: it's not clear if we need to check every given function or
+        // checking on this level is enough. At this moment it's better to stay here 
+        // for performance reason.
+        if (IsFunctionSetFromPython(aDescr)) {
+          MESSAGE("Function set from Python. Do process with updated description.");
+          return UPDATE_DESCRIPTION;
+        }
+
+        MESSAGE("The dependency label is not in processed list. Do not process.");
+        return NOT_PROCESS;
+      }
+    }
+
+    MESSAGE("OK. Do process the function.");
+    return TO_PROCESS;
+  }
+
+  //================================================================================
+  /*!
+  * \brief Adds function's object to ignored for Python dump output
+  */
+  //================================================================================
+  void AddFuncObjectToIgnored(const Handle(GEOM_Function)& theFunction, std::set<TCollection_AsciiString>& theIgnoreObjs)
+  {
+    TCollection_AsciiString anObjEntry;
+    TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
+    theIgnoreObjs.insert(anObjEntry);
+  }
+
+}
+
+
 //================================================================================
 /*!
  * \brief Fix up the name of python variable
@@ -1084,62 +1202,62 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
                      bool&                              theIsDumpCollected)
 {
   theIsDumpCollected = false;
-  if (theFunction.IsNull()) return false;
 
-  if (theProcessed.Contains(theFunction->GetEntry())) return false;
+  if (theFunction.IsNull()) {
+    MESSAGE("Can't process a null function! Return.");
+    return false;
+  }
 
-  // pass functions, that depends on nonexisting ones
-  bool doNotProcess = false;
-  TDF_LabelSequence aSeq;
-  theFunction->GetDependency(aSeq);
-  Standard_Integer aLen = aSeq.Length();
-  for (Standard_Integer i = 1; i <= aLen && !doNotProcess; i++) {
-    TDF_Label aRefLabel = aSeq.Value(i);
-    Handle(TDF_Reference) aRef;
-    if (!aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
-      doNotProcess = true;
-    }
-    else {
-      if (aRef.IsNull() || aRef->Get().IsNull()) {
-        doNotProcess = true;
-      }
-      else {
-        Handle(TDataStd_TreeNode) aT;
-        if (!TDataStd_TreeNode::Find(aRef->Get(), aT)) {
-          doNotProcess = true;
-        }
-        else {
-          TDF_Label aDepLabel = aT->Label();
-          Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(aDepLabel);
+  TCollection_AsciiString aDescr = theFunction->GetDescription();
+  MESSAGE("The function description: " << aDescr);
 
-          if (aFunction.IsNull()) doNotProcess = true;
-          else if (!theProcessed.Contains(aDepLabel)) doNotProcess = true;
-        }
-      }
-    }
-  }
+  if (theProcessed.Contains(theFunction->GetEntry()))
+    return false;
 
-  if (doNotProcess) {
-    TCollection_AsciiString anObjEntry;
-    TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
-    theIgnoreObjs.insert(anObjEntry);
+  // Check if a given function depends on nonexisting ones
+  const FunctionProcessType funcProcessType = GetFunctionProcessingType(theFunction, theProcessed, aDescr);
+  switch (funcProcessType)
+  {
+  case TO_PROCESS:
+    // Just process it
+    break;
+
+  case NOT_PROCESS:
+  {
+    // We don't need this function and its object in a dump
+    AddFuncObjectToIgnored(theFunction, theIgnoreObjs);
     return false;
   }
+
+  case UPDATE_DESCRIPTION:
+    // Edge case for a function that was dumped from Python.
+    // Get rid of the parent function description.
+    UpdateFuncFromPythonDescription(aDescr);
+    // A result object is already added by an algo script, then
+    // if we keep it in the dump it will be added twice on the script loading.
+    AddFuncObjectToIgnored(theFunction, theIgnoreObjs);
+    break;
+
+  default:
+    MESSAGE("Wrong type of the function processing!" << funcProcessType);
+    break;
+  }
+
   theProcessed.Add(theFunction->GetEntry());
 
-  TCollection_AsciiString aDescr = theFunction->GetDescription();
-  if(aDescr.Length() == 0) return false;
+  // Check the length only after its fucntion was added to the processed!
+  if(!aDescr.Length())
+    return false;
 
-  //Check if its internal function which doesn't requires dumping
-  if(aDescr == "None") return false;
+  // Check if it's an internal function which doesn't require dumping
+  if(aDescr == "None")
+    return false;
 
   //Check the very specific case of RestoreShape function,
   //which is not dumped, but the result can be published by the user.
   //We do not publish such objects to decrease danger of dumped script failure.
   if(aDescr.Value(1) == '#') {
-    TCollection_AsciiString anObjEntry;
-    TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
-    theIgnoreObjs.insert(anObjEntry);
+    AddFuncObjectToIgnored(theFunction, theIgnoreObjs);
     return false;
   }
 
@@ -1156,6 +1274,9 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
 
   //Replace parameter by notebook variables
   ReplaceVariables(aDescr,theVariables);
+  // Check description, because we could lose entire command during variable processing
+  if (aDescr.IsEmpty())
+    return false;
 
   //Process sketcher functions, replacing string command by calls to Sketcher interface
   if ( ( aDescr.Search( "MakeSketcherOnPlane" ) != -1 ) || ( aDescr.Search( "MakeSketcher" ) != -1 ) ) {
@@ -1295,8 +1416,7 @@ Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theStrin
 void ReplaceVariables(TCollection_AsciiString& theCommand,
                       const TVariablesList&    theVariables)
 {
-  if (SALOME::VerbosityActivated())
-    std::cout<<"Command : "<<theCommand<<std::endl;
+  MESSAGE("Command : " << theCommand);
 
   if (SALOME::VerbosityActivated()) {
     std::cout<<"All Entries:"<<std::endl;
@@ -1312,8 +1432,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     if( aCommand.Length() == 0 )
       break;
 
-    if (SALOME::VerbosityActivated())
-      std::cout<<"Sub-command : "<<aCommand<<std::endl;
+    MESSAGE("Sub-command : " << aCommand);
 
     Standard_Integer aStartCommandPos = theCommand.Location(aCommand,1,theCommand.Length());
     Standard_Integer aEndCommandPos = aStartCommandPos + aCommand.Length();
@@ -1330,8 +1449,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     //Remove white spaces
     anEntry.RightAdjust();
     anEntry.LeftAdjust();
-    if(SALOME::VerbosityActivated())
-      std::cout<<"Result entry : '" <<anEntry<<"'"<<std::endl;
+    MESSAGE("Result entry : '" << anEntry << "'");
 
     if ( anEntry.IsEmpty() ) {
       aCommandIndex++;
@@ -1348,8 +1466,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       anEntry.Remove( 1, 1 );
       anEntry.RightAdjust();
       anEntry.LeftAdjust();
-      if(SALOME::VerbosityActivated())
-                   std::cout<<"Sub-entry : '" <<anEntry<<"'"<<std::endl;
+      MESSAGE("Sub-entry : '" << anEntry << "'");
     }
 
     //Find variables used for object construction
@@ -1359,9 +1476,13 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       aStates = (*it).second;
 
     if(!aStates) {
-      if(SALOME::VerbosityActivated())
-                   std::cout<<"Valiables list empty!!!"<<std::endl;
+      MESSAGE("Can't find an entry among study objects!");
+      // We can't skip this because the entry can be used with automatically assigned name
+      // like "geomObj_1" to create other objects. Some tests will fail without this.
+      // MESSAGE("Can't find an entry among study objects! Skip this command.");
+      // theCommand.Remove(aStartCommandPos, aEndCommandPos - aStartCommandPos);
       aCommandIndex++;
+
       continue;
     }
 
@@ -1378,8 +1499,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     while(aCommand.Location(aTotalNbParams,COMMA,1,aCommand.Length()))
       aTotalNbParams++;
 
-    if(SALOME::VerbosityActivated())
-           std::cout<<"aTotalNbParams = "<<aTotalNbParams<<std::endl;
+    MESSAGE("aTotalNbParams = " << aTotalNbParams);
 
     Standard_Integer aFirstParam = aNbEntries;
 
@@ -1420,15 +1540,13 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
       if ( aStartPos == aEndPos )
         continue; // PAL20889: for "[]"
 
-      if(SALOME::VerbosityActivated())
-        std::cout<<"aStartPos = "<<aStartPos<<", aEndPos = "<<aEndPos<<std::endl;
+      MESSAGE("aStartPos = " << aStartPos << ", aEndPos = " << aEndPos);
 
       aVar = aCommand.SubString(aStartPos, aEndPos-1);
       aVar.RightAdjust();
       aVar.LeftAdjust();
 
-      if(SALOME::VerbosityActivated())
-        std::cout<<"Variable: '"<< aVar <<"'"<<std::endl;
+      MESSAGE("Variable: '" << aVar << "'");
 
       // specific case for sketcher
       if(aVar.Location( TCollection_AsciiString("Sketcher:"), 1, aVar.Length() ) != 0) {
@@ -1447,8 +1565,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
             aEndSectionPos = aVar.Length();
 
           aSection = aVar.SubString(aStartSectionPos, aEndSectionPos-1);
-          if(SALOME::VerbosityActivated())
-                             std::cout<<"aSection: "<<aSection<<std::endl;
+          MESSAGE("aSection: " << aSection);
 
           Standard_Integer aNbParams = 1;
           while( aSection.Location( aNbParams, ' ', 1, aSection.Length() ) )
@@ -1464,15 +1581,13 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
             else
               aEndParamPos = aSection.Length() + 1;
 
-            if(SALOME::VerbosityActivated())
-              std::cout<<"aParamIndex: "<<aParamIndex<<" aStartParamPos: " <<aStartParamPos<<" aEndParamPos: "<<aEndParamPos<<std::endl;
+            MESSAGE("aParamIndex: " << aParamIndex << " aStartParamPos: " << aStartParamPos << " aEndParamPos: " << aEndParamPos);
 
             if ( aStartParamPos == aEndParamPos)
               continue;
 
             aParameter = aSection.SubString(aStartParamPos, aEndParamPos-1);
-            if(SALOME::VerbosityActivated())
-                               std::cout<<"aParameter: "<<aParameter<<std::endl;
+            MESSAGE("aParameter: " << aParameter);
 
             if(iVar >= aVariables.size())
               continue;
@@ -1488,31 +1603,25 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
               aReplacedParameter.InsertAfter(aReplacedParameter.Length(),"'");
             }
 
-            if(SALOME::VerbosityActivated())
-                               std::cout<<"aSection before : "<<aSection<< std::endl;
+            MESSAGE("aSection before : " << aSection);
             aSection.Remove(aStartParamPos, aEndParamPos - aStartParamPos);
             aSection.Insert(aStartParamPos, aReplacedParameter);
-            if(SALOME::VerbosityActivated())
-              std::cout<<"aSection after  : "<<aSection<<std::endl<<std::endl;
+            MESSAGE("aSection after  : " << aSection << '\n');
             iVar++;
           }
 
-          if(SALOME::VerbosityActivated())
-            std::cout<<"aVar before : "<<aVar<<std::endl;
+          MESSAGE("aVar before : " << aVar);
 
           aVar.Remove(aStartSectionPos, aEndSectionPos - aStartSectionPos);
           aVar.Insert(aStartSectionPos, aSection);
 
-          if(SALOME::VerbosityActivated())
-            std::cout<<"aVar after  : "<<aVar<<std::endl<<std::endl;
+          MESSAGE("aVar after  : " << aVar << '\n');
         }
 
-        if(SALOME::VerbosityActivated())
-          std::cout<<"aCommand before : "<<aCommand<<std::endl;
+        MESSAGE("aCommand before : " << aCommand);
         aCommand.Remove(aStartPos, aEndPos - aStartPos);
         aCommand.Insert(aStartPos, aVar);
-        if(SALOME::VerbosityActivated())
-          std::cout<<"aCommand after  : "<<aCommand<<std::endl;
+        MESSAGE("aCommand after  : " << aCommand);
 
         break;
       } // end of specific case for sketcher
@@ -1548,8 +1657,7 @@ void ReplaceVariables(TCollection_AsciiString& theCommand,
     aStates->IncrementState();
   }
 
-  if (SALOME::VerbosityActivated())
-    std::cout<<"Command : "<<theCommand<<std::endl;
+  MESSAGE("Command after replacing of the variables: " << theCommand);
 }
 
 //=============================================================================
index 6c0e11d75979f85bd202d33005f4a070af0e2d16..f345d2d8937f570bb45fd7f79060b2c948d97044 100644 (file)
@@ -1930,13 +1930,19 @@ bool GeometryGUI::activateModule( SUIT_Study* study )
     PyErr_Print();
   }
   else {
-    PyObject* result =
-      PyObject_CallMethod(pluginsmanager, (char*)"initialize", (char*)"isss", 1, "geom",
-                          tr("MEN_NEW_ENTITY").toUtf8().data(),
-                          tr("GEOM_PLUGINS_OTHER").toUtf8().data());
-    if ( !result )
-      PyErr_Print();
-    Py_XDECREF(result);
+    auto addPluginsManager = [&](const char* managerName, const char* menuName, const char* submenuName) -> void
+    {
+      PyObject* result = PyObject_CallMethod(
+        pluginsmanager, (char*)"initialize", (char*)"isss", 1, managerName, menuName, submenuName);
+
+      if ( !result )
+        PyErr_Print();
+
+      Py_XDECREF(result);
+    };
+
+    addPluginsManager("geom", tr("MEN_NEW_ENTITY").toUtf8().data(), tr("GEOM_PLUGINS_OTHER").toUtf8().data());
+    addPluginsManager("geomrepairadv", tr("MEN_REPAIR").toUtf8().data(), tr("MEN_ADVANCED").toUtf8().data());
   }
   PyGILState_Release(gstate);
   // end of GEOM plugins loading
index 91f909c39827d40d2475a697189072da1d96d160..39e9d6980548b8fd0f261a488a1bb7ef1b9c1233 100644 (file)
@@ -1212,3 +1212,32 @@ Handle(GEOM_Object) GEOMImpl_IHealingOperations::LimitTolerance (Handle(GEOM_Obj
   SetErrorCode(OK);
   return aNewObject;
 }
+
+//=============================================================================
+/*!
+ *  FuncToPythonDump
+ *
+ *  This function doesn't do any healing.
+ *  Provides Python dump functionality for algorithms entirely implemented in Python.
+ */
+//=============================================================================
+  void GEOMImpl_IHealingOperations::FuncToPythonDump(
+    Handle(GEOM_Object) theObject,
+    Handle(GEOM_Object) result,
+    const char* imports,
+    const char* funcName,
+    const char* args
+  )
+  {
+    // Find a function to append a command
+    Handle(GEOM_Function) aFunction = result->GetLastFunction();
+    if (aFunction.IsNull())
+    {
+      MESSAGE("Can't get last function to append Python dump!");
+      return;
+    } 
+
+    // Make a Python command - it will be appended to the given function
+    GEOM::TPythonDump pd (aFunction, true);
+    pd << imports << result << " = " << funcName << "(" << theObject << ", " << args << ")";
+  }
index 6287cf8eee47587aea8a118b051e7f4f3d9ddbf0..ac9b0dfe69f1a66d89a52842bbc2605afbe4bc3c 100644 (file)
@@ -106,6 +106,17 @@ class GEOMImpl_IHealingOperations : public GEOM_IOperations {
                                                       double theTolerance,
                                                       TopAbs_ShapeEnum theType = TopAbs_SHAPE );
 
+  // This function doesn't do any healing.
+  // The only goal is to provide Python dump functionality for 
+  // algorithms entirely implemented in Python.
+  void FuncToPythonDump(
+    Handle(GEOM_Object) theObject,
+    Handle(GEOM_Object) result,
+    const char* imports,
+    const char* funcName,
+    const char* args
+  );
+
   const ShHealOper_ModifStats* GetStatistics() { return myModifStats; }
 
 private:
index e2fb0c91fb977544c60566e70dea26878b93fb05..04bea6ac1f03c329ce59ed2d6d5906d313feb703 100644 (file)
 #define SEWING_NON_MANIFOLD   11
 #define REMOVE_INTERNAL_FACES 12
 #define DIVIDE_EDGE_BY_POINT  13
+#define FUNC_TO_PYTHON_DUMP   13
 
 #define BASIC_FILLING 1
 #define FILLING_ON_CONSTRAINTS 2
index e832f7643a8d6d0937445627af0d37e2031ba534..1b57c036bc7ddec9dba98d0f01c06637d748a946 100644 (file)
@@ -637,6 +637,26 @@ GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::LimitTolerance (GEOM::GEOM_Obje
   return GetObject(aNewObject);
 }
 
+//=============================================================================
+/*!
+ *  LimitTolerance
+ */
+//=============================================================================
+void GEOM_IHealingOperations_i::FuncToPythonDump (
+  GEOM::GEOM_Object_ptr theObject,
+  GEOM::GEOM_Object_ptr result,
+  const char* imports,
+  const char* funcName,
+  const char* args)
+{
+  // Get the objects
+  Handle(::GEOM_Object) anObject = GetObjectImpl(theObject);
+  Handle(::GEOM_Object) aResult = GetObjectImpl(result);
+
+  // Perform
+  GetOperations()->FuncToPythonDump(anObject, aResult, imports, funcName, args);
+}
+
 //================================================================================
 /*!
  * \brief Return information on what has been done by the last called healing method
index 4c00234e5bc551dba72831f8d8ecc3fe50d35107..6a907b93f22da37f048e78a895e9fdc6a2a0cde8 100644 (file)
@@ -99,6 +99,16 @@ class GEOM_I_EXPORT GEOM_IHealingOperations_i :
    GEOM::GEOM_Object_ptr LimitTolerance (GEOM::GEOM_Object_ptr theObject,
                                          CORBA::Double theTolerance);
 
+   // The only goal is to provide Python dump functionality for 
+   // algorithms entirely implemented in Python.
+   void FuncToPythonDump(
+     GEOM::GEOM_Object_ptr theObject,
+     GEOM::GEOM_Object_ptr result,
+     const char* imports,
+     const char* funcName,
+     const char* args
+   );
+
    ::GEOMImpl_IHealingOperations* GetOperations() { return (::GEOMImpl_IHealingOperations*)GetImpl(); }
 
    GEOM::ModifStatistics* GetStatistics();
index d1fee65e2e92f46ba3aa3e2c2dbec1f056585727..9564a2309673cf8f2b2189c5bd476b5da4d6dff2 100644 (file)
@@ -7483,6 +7483,26 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
             self._autoPublish(anObj, theName, "limitTolerance")
             return anObj
 
+        ## Provides Python dump functionality for algorithms entirely implemented in Python.
+        #  @param theObject Shape to be processed.
+        #  @param result Shape of the algorithm execution.
+        #  @param imports module import for current functon..
+        #  @param funcName name of a Python function that we need to put into dump.
+        #  @param args arguments of the Python function.
+        #
+        def FuncToPythonDump(self, theObject, result, imports, funcName, args):
+            """
+            Provides Python dump functionality for algorithms entirely implemented in Python.
+
+            Parameters:
+                theObject Shape to be processed.
+                result Shape of the algorithm execution.
+                imports module import for current functon.
+                funcName name of a Python function that we need to put into dump.
+                args arguments of the Python function.
+            """
+            self.HealOp.FuncToPythonDump(theObject, result, imports, funcName, args)
+
         ## Get a list of wires (wrapped in GEOM.GEOM_Object-s),
         #  that constitute a free boundary of the given shape.
         #  @param theObject Shape to get free boundary of.
index 76fb0d259d9213613395d40b3aa7deed9b848c1d..041c5b96ba857e2a6c12a38a1eccac82883c3104 100644 (file)
@@ -94,3 +94,27 @@ std::vector<int> GEOM_Swig_LocalSelector::getSelection()
   return ids;
 }
 
+void GEOM_Swig_LocalSelector::setSelection(const std::vector<int> ids)
+{
+  MESSAGE("setSelection() start...");
+
+  SalomeApp_Application* app = (SalomeApp_Application*)SUIT_Session::session()->activeApplication();
+  LightApp_SelectionMgr* aSelMgr = app->selectionMgr();
+  SALOME_ListIO aSelList;
+  aSelMgr->selectedObjects(aSelList);
+
+  MESSAGE("aSelList.Extent(): " << aSelList.Extent());
+  if (!aSelList.Extent())
+  {
+    return;
+  }
+
+  TColStd_IndexedMapOfInteger idsMap;
+  for (const auto i : ids)
+  {
+    idsMap.Add(i);
+  }
+
+  Handle(SALOME_InteractiveObject) anIO = aSelList.First();
+  aSelMgr->selectObjects(anIO, idsMap, false);
+}
index f934286ee05dcf25db0b768841c76944138b498c..5b2dc0e3cc587872badbc4a566b229655d3da1ae 100644 (file)
@@ -37,6 +37,7 @@ public:
   ~GEOM_Swig_LocalSelector();
   
   std::vector<int> getSelection();
+  void setSelection(const std::vector<int> ids);
 
 protected:
   GEOM::GEOM_Object_var              myObject;
index 3358d39e35fc8b42ad23e2c32db943359c11fb63..65571632c7b7885fd53ba9f4c7a36910fa4c5299 100644 (file)
@@ -66,6 +66,14 @@ GEOM_Swig::GEOM_Swig( bool updateOB )
 */
 GEOM_Swig::~GEOM_Swig()
 {
+  // Delete selector because of sigsegv in TEventInitLocalSelection::Execute()
+  // when call GEOM_Swig.initLocalSelection() from Python, close the study, create a new one and
+  // call it again.
+  if (myOCCSelector)
+  {
+    delete myOCCSelector;
+    myOCCSelector = nullptr;
+  }
 }
 
 /*!
@@ -579,6 +587,33 @@ std::vector<int> GEOM_Swig::getLocalSelection()
   return result;
 }
 
+
+/*!libGEOM_Swig
+  \brief Set local subShapes selection on a given shape
+  \param ids sub-shapes ids
+ */
+void GEOM_Swig::setLocalSelection(const std::vector<int> ids)
+{
+  class TEventSetLocalSelection: public SALOME_Event
+  {
+  public:
+    typedef std::vector<int> TResult;
+    TResult myIds;
+    TResult myResult;
+
+    TEventSetLocalSelection(const std::vector<int> _ids) : myIds(_ids) {}
+
+    virtual void Execute()
+    {
+      MESSAGE("TEventSetLocalSelection myLocalSelector: " << myLocalSelector);
+      if (myLocalSelector)
+        myLocalSelector->setSelection(myIds);
+    }
+  };
+
+  ProcessEvent(new TEventSetLocalSelection(ids));
+}
+
 /*!
   \brief close local subShapes selection on a given shape
  */
index 8781d35898ff65a5d081be26bf4191765caf518d..f653492c605d6b67e1157ab836c6127655c39d47 100644 (file)
@@ -56,6 +56,7 @@ public:
 
   GEOMGUI_EXPORT void initLocalSelection( const char* theEntry, int theMode);
   GEOMGUI_EXPORT std::vector<int> getLocalSelection();
+  GEOMGUI_EXPORT void setLocalSelection(const std::vector<int> ids);
   GEOMGUI_EXPORT void closeLocalSelection();
 
   GEOMGUI_EXPORT int         getIndexTopology( const char* theSubIOR, const char* theMainIOR );
index e6ccf97eb196c00e885bbc82994b429b01934f2f..100a41e963c2d0c658372ac63dae228f8504a147 100644 (file)
@@ -83,6 +83,7 @@ class GEOM_Swig
 
   void initLocalSelection( const char* theEntry, int theMode);
   std::vector<int> getLocalSelection();
+  void setLocalSelection(const std::vector<int> ids);
   void closeLocalSelection();
 
   int         getIndexTopology( const char* theSubIOR, const char* theMainIOR );