Salome HOME
Merge V8_4_BR branch.
[modules/geom.git] / src / GEOM / GEOM_Engine.cxx
index b83233ff5f761d28902d155ee9c7c4216bac0c54..dd4bc10126af391032cf63bed182c38951086002 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
@@ -26,7 +26,6 @@
 
 #include "GEOM_Engine.hxx"
 
-#include "GEOM_DataMapIteratorOfDataMapOfAsciiStringTransient.hxx"
 #include "GEOM_Field.hxx"
 #include "GEOM_Function.hxx"
 #include "GEOM_ISubShape.hxx"
@@ -35,8 +34,6 @@
 #include "GEOM_SubShapeDriver.hxx"
 #include "Sketcher_Profile.hxx"
 
-#include <Basics_OCCTVersion.hxx>
-
 #include "utilities.h"
 
 #include <Basics_Utils.hxx>
 #include <TColStd_MapOfTransient.hxx>
 #include <TColStd_HSequenceOfInteger.hxx>
 
-#include <TColStd_HArray1OfByte.hxx>
 #include <TColStd_DataMapIteratorOfDataMapOfIntegerTransient.hxx>
 
 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
 
+#include <BinDrivers.hxx>
+#include <StdDrivers_DocumentRetrievalDriver.hxx>
+#include <PCDM_StorageDriver.hxx>
+
 #include <set>
 
 #include <Standard_Failure.hxx>
@@ -86,9 +86,18 @@ static int MYDEBUG = 0;
 static int MYDEBUG = 0;
 #endif
 
+// VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
+// Next macro, when defined, causes appearing of SubShapeAllIDs(), SubShapeAllSortedIDs(), GetSameIDs()
+// and other such commands in Python dump.
+// See also GEOMImpl_IShapesOperations.cxx.
+// ---------------------------------------
+// #define DUMP_SUBSHAPE_IDS
+// ---------------------------------------
+
 typedef std::map< TCollection_AsciiString, TCollection_AsciiString > TSting2StringMap;
 typedef std::map< TCollection_AsciiString, TObjectData >             TSting2ObjDataMap;
 typedef std::map< TCollection_AsciiString, TObjectData* >            TSting2ObjDataPtrMap;
+typedef std::map< int, std::list < int > >                           TIntToListIntMap;
 
 static GEOM_Engine* TheEngine = NULL;
 
@@ -124,6 +133,11 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
                      std::set<TCollection_AsciiString>& theIgnoreObjs,
                      bool&                              theIsDumpCollected);
 
+static int GetTag(const TCollection_AsciiString &theEntry);
+
+static void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                               TIntToListIntMap      &theRefMap);
+
 void ReplaceVariables(TCollection_AsciiString& theCommand,
                       const TVariablesList&    theVariables);
 
@@ -149,6 +163,14 @@ void PublishObject (TObjectData&                              theObjectData,
                     std::map< int, TCollection_AsciiString >& theEntryToCmdMap,
                     std::set<TCollection_AsciiString>&        theMapOfPublished);
 
+static TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished);
+
+void Prettify(TCollection_AsciiString& theScript);
+
 //================================================================================
 /*!
  * \brief Fix up the name of python variable
@@ -215,6 +237,9 @@ GEOM_Engine::GEOM_Engine()
   TFunction_DriverTable::Get()->AddDriver(GEOM_Object::GetSubShapeID(), new GEOM_SubShapeDriver());
   
   _OCAFApp = new GEOM_Application();
+  _OCAFApp->DefineFormat("SALOME_GEOM", "GEOM Document Version 1.0", "sgd",
+                         new StdDrivers_DocumentRetrievalDriver, 0);
+  BinDrivers::DefineFormat(_OCAFApp);
   _UndoLimit = 0;
 }
 
@@ -254,7 +279,7 @@ Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID, bool force)
     aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID));
   }
   else if (force) {
-    _OCAFApp->NewDocument("SALOME_GEOM", aDoc);
+    _OCAFApp->NewDocument("BinOcaf", aDoc);
     aDoc->SetUndoLimit(_UndoLimit);
     _mapIDDocument.Bind(theDocID, aDoc);
     TDataStd_Integer::Set(aDoc->Main(), theDocID);
@@ -408,18 +433,15 @@ Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object)              th
   aSSI.SetIndices(theIndices);
 
   try {
-#if OCC_VERSION_LARGE > 0x06010000
     OCC_CATCH_SIGNALS;
-#endif
     GEOM_Solver aSolver (GEOM_Engine::GetEngine());
     if (!aSolver.ComputeFunction(aFunction)) {
       MESSAGE("GEOM_Engine::AddSubShape Error: Can't build a sub shape");
       return NULL;
     }
   }
-  catch (Standard_Failure) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail->GetMessageString());
+  catch (Standard_Failure& aFail) {
+    MESSAGE("GEOM_Engine::AddSubShape Error: " << aFail.GetMessageString());
     return NULL;
   }
 
@@ -496,7 +518,7 @@ bool GEOM_Engine::RemoveObject(Handle(GEOM_BaseObject)& theObject)
   if ( aFreeLabels.empty() || aFreeLabels.back() != aLabel )
     aFreeLabels.push_back(aLabel);
 
-  // we can't explicitely delete theObject. At least prevent its functioning
+  // we can't explicitly delete theObject. At least prevent its functioning
   // as an alive object when aLabel is reused for a new object
   theObject->_label = aLabel.Root();
   theObject->_ior.Clear();
@@ -555,6 +577,11 @@ bool GEOM_Engine::Load(int theDocID, const char* theFileName)
     return false;
   }
 
+  // Replace old document format by the new one.
+  if (aDoc->StorageFormat().IsEqual("SALOME_GEOM")) {
+    aDoc->ChangeStorageFormat("BinOcaf");
+  }
+
   aDoc->SetUndoLimit(_UndoLimit);
 
   if(_mapIDDocument.IsBound(theDocID)) _mapIDDocument.UnBind(theDocID);
@@ -639,7 +666,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   // a map containing copies of TObjectData from theObjectData
   TSting2ObjDataMap    aEntry2ObjData;
   // contains pointers to TObjectData of either aEntry2ObjData or theObjectData; the latter
-  // occures when several StudyEntries correspond to one Entry
+  // occurs when several StudyEntries correspond to one Entry
   TSting2ObjDataPtrMap aStEntry2ObjDataPtr;
 
   //Resource_DataMapOfAsciiStringAsciiString aEntry2StEntry, aStEntry2Entry, theObjectNames;
@@ -677,6 +704,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   // Mantis issue 0020768
   Standard_Integer objectCounter = 0;
   Resource_DataMapOfAsciiStringAsciiString aNameToEntry;
+  TIntToListIntMap                         aRefMap;
 
   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
     TDataStd_ChildNodeIterator Itr(aRoot);
@@ -705,6 +733,10 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
             continue; // aCurScript is already at the end of aFuncScript
         aFuncScript += aCurScript;
       }
+
+      // Fill the map of references.
+      FillMapOfRef(aFunction, aRefMap);
+
       if (isDumpCollected ) {
         // Replace entries by the names
         ReplaceEntriesByNames( aFuncScript, aEntry2ObjData, isPublished,
@@ -720,9 +752,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                          aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
         }
         // add publishing commands to the script
+        std::set< int >                                    aPublished;
         std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-          aFuncScript += anEntryToCmd->second;
+
+        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+          const TCollection_AsciiString aPublishCmds =
+              GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                                 aRefMap, aPublished);
+
+          aFuncScript += aPublishCmds;
+        }
 
         // PTv, 0020001 add result objects from RestoreGivenSubShapes into ignore list,
         //  because they will be published during command execution
@@ -775,9 +814,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                      aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
     }
     // add publishing commands to the script
+    std::set< int >                                    aPublished;
     std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-      aScript += anEntryToCmd->second;
+
+    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+      const TCollection_AsciiString aPublishCmds =
+          GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                             aRefMap, aPublished);
+
+      aScript += aPublishCmds;
+    }
   }
 
   //RNV: issue 16219: EDF PAL 469: "RemoveFromStudy" Function
@@ -820,6 +866,11 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
     aScript.Insert( posToInsertGlobalVars, globalVars );
   }
 
+  // VSR 29/08/2017: 0023327, 0023428: eliminate unnecessary lines in Python dump
+#ifndef DUMP_SUBSHAPE_IDS
+  Prettify(aScript);
+#endif
+
   return aScript;
 }
 
@@ -860,11 +911,7 @@ Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const
 #define TEXTURE_LABEL_DATA     5
 
 int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight,
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
                             const Handle(TColStd_HArray1OfByte)& theTexture,
-#else
-                            const Handle(TDataStd_HArray1OfByte)& theTexture,
-#endif
                             const TCollection_AsciiString& theFileName)
 {
   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
@@ -909,19 +956,11 @@ int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight,
   return aTextureID;
 }
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
 Handle(TColStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID,
-#else
-Handle(TDataStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID,
-#endif
                                                       int& theWidth, int& theHeight,
                                                       TCollection_AsciiString& theFileName)
 {
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
   Handle(TColStd_HArray1OfByte) anArray;
-#else
-  Handle(TDataStd_HArray1OfByte) anArray;
-#endif
   theWidth = theHeight = 0;
 
   Handle(TDocStd_Document) aDoc = GetDocument(theDocID);
@@ -1212,6 +1251,67 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
   return true;
 }
 
+//=============================================================================
+/*!
+ *  GetTag: Returns the tag from entry
+ */
+//=============================================================================
+int GetTag(const TCollection_AsciiString &theEntry)
+{
+  const int aGeomObjDepth = 3;
+  const int aTag          = theEntry.Token(":", aGeomObjDepth).IntegerValue();
+
+  return aTag;
+}
+
+//=============================================================================
+/*!
+ *  FillMapOfRef: Fill the map of references
+ */
+//=============================================================================
+void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                        TIntToListIntMap      &theRefMap)
+{
+  TDF_LabelSequence       aSeq;
+  TCollection_AsciiString anObjEntry;
+  int                     anObjTag;
+
+  TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
+  anObjTag = GetTag(anObjEntry);
+  theFunction->GetDependency(aSeq);
+
+  const Standard_Integer aLen = aSeq.Length();
+  Standard_Integer       i;
+
+  for (i = 1; i <= aLen; i++) {
+    TDF_Label             aRefLabel = aSeq.Value(i);
+    Handle(TDF_Reference) aRef;
+
+    if (aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
+      if (!aRef.IsNull() && !aRef->Get().IsNull()) {
+        Handle(TDataStd_TreeNode) aT;
+
+        if (TDataStd_TreeNode::Find(aRef->Get(), aT)) {
+          TDF_Label             aDepLabel = aT->Label();
+          Handle(GEOM_Function) aRefFunct = GEOM_Function::GetFunction(aDepLabel);
+
+          if (!aRefFunct.IsNull()) {
+            // Get entry of the referenced object.
+            TDF_Tool::Entry(aRefFunct->GetOwnerEntry(), anObjEntry);
+
+            const int aRefTag = GetTag(anObjEntry);
+
+            if (anObjTag != aRefTag) {
+              // Avoid making references for operations without copy.
+              theRefMap[anObjTag].push_back(aRefTag);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 //=============================================================================
 /*!
  *  FindEntries: Returns a sequence of start/end positions of entries in the string
@@ -1661,11 +1761,7 @@ void AddObjectColors (int                      theDocID,
   }
 }
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
 static TCollection_AsciiString pack_data (const Handle(TColStd_HArray1OfByte)& aData)
-#else
-static TCollection_AsciiString pack_data (const Handle(TDataStd_HArray1OfByte)& aData)
-#endif
 {
   TCollection_AsciiString stream;
   if (!aData.IsNull()) {
@@ -1693,11 +1789,7 @@ void AddTextures (int theDocID, TCollection_AsciiString& theScript)
       if (*it <= 0) continue;
       Standard_Integer aWidth, aHeight;
       TCollection_AsciiString aFileName;
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
       Handle(TColStd_HArray1OfByte) aTexture =
-#else
-      Handle(TDataStd_HArray1OfByte) aTexture =
-#endif
         engine->getTexture(theDocID, *it, aWidth, aHeight, aFileName);
       if (aWidth > 0 && aHeight > 0 && !aTexture.IsNull() && aTexture->Length() > 0 ) {
         TCollection_AsciiString aCommand = "\n\t";
@@ -1749,8 +1841,6 @@ void PublishObject (TObjectData&                              theObjectData,
   if ( stEntry2DataPtr != theStEntry2ObjDataPtr.end() )
     aFatherData = stEntry2DataPtr->second;
 
-  const int geomObjDepth = 3;
-
   // treat multiply published object
   if ( theObjectData._pyName.IsEmpty() )
   {
@@ -1764,8 +1854,8 @@ void PublishObject (TObjectData&                              theObjectData,
     aCreationCommand += theObjectData._pyName + " = " + data0._pyName;
 
     // store aCreationCommand before publishing commands
-    int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
-    theEntryToCmdMap.insert( std::make_pair( tag + 2*theEntry2ObjData.size(), aCreationCommand ));
+    int tag = GetTag(theObjectData._entry);
+    theEntryToCmdMap.insert( std::make_pair( tag + -2*theEntry2ObjData.size(), aCreationCommand ));
   }
 
   // make a command
@@ -1779,12 +1869,94 @@ void PublishObject (TObjectData&                              theObjectData,
   aCommand += theObjectData._pyName + ", '" + theObjectData._name + "' )";
 
   // bind a command to the study entry
-  int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
+  int tag = GetTag(theObjectData._entry);
   theEntryToCmdMap.insert( std::make_pair( tag, aCommand ));
 
   theObjectData._studyEntry.Clear(); // not to publish any more
 }
 
+//================================================================================
+/*!
+ * \brief Returns the string of publishing commands. Take into account that
+ *  references should be published prior to the objects refer to them.
+ */
+//================================================================================
+TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished)
+{
+  TCollection_AsciiString aResult;
+
+  if (!thePublished.count(theTag)) {
+    // This object is not published yet.
+    std::map< int, TCollection_AsciiString >::const_iterator anIt =
+      theEntryToCmdMap.find(theTag);
+
+    if (anIt != theEntryToCmdMap.end()) {
+      // There is a pubish cmd.
+      TIntToListIntMap::const_iterator aRefIt = theMapRefs.find(theTag);
+
+      if (aRefIt != theMapRefs.end()) {
+        // Recursively publish all references.
+        std::list< int >::const_iterator aRefTagIt = aRefIt->second.begin();
+
+        for(; aRefTagIt != aRefIt->second.end(); ++aRefTagIt) {
+          const TCollection_AsciiString aRefCmd = GetPublishCommands
+            (*aRefTagIt, theEntryToCmdMap, theMapRefs, thePublished);
+
+          aResult += aRefCmd;
+        }
+      }
+
+      // Add the object command.
+      aResult += anIt->second;
+    }
+
+    thePublished.insert(theTag);
+  }
+
+  return aResult;
+}
+
+void Prettify(TCollection_AsciiString& theScript)
+{
+  TCollection_AsciiString output;
+  static std::list<TCollection_AsciiString> ToRemove;
+  if (ToRemove.empty()) {
+    ToRemove.push_back("geompy.SubShapeAllIDs");
+    ToRemove.push_back("geompy.SubShapeAllSortedCentresIDs");
+    ToRemove.push_back("geompy.SubShapeAllSortedIDs");
+    ToRemove.push_back("geompy.GetFreeFacesIDs");
+    ToRemove.push_back("geompy.GetShapesOnBoxIDs");
+    ToRemove.push_back("geompy.GetShapesOnShapeIDs");
+    ToRemove.push_back("geompy.GetShapesOnPlaneIDs");
+    ToRemove.push_back("geompy.GetShapesOnPlaneWithLocationIDs");
+    ToRemove.push_back("geompy.GetShapesOnCylinderIDs");
+    ToRemove.push_back("geompy.GetShapesOnCylinderWithLocationIDs");
+    ToRemove.push_back("geompy.GetShapesOnSphereIDs");
+    ToRemove.push_back("geompy.GetShapesOnQuadrangleIDs");
+    ToRemove.push_back("geompy.GetSameIDs");
+  }
+
+  int start = 1;
+  while (start <= theScript.Length()) {
+    int end = theScript.Location("\n", start, theScript.Length());
+    if (end == -1) end = theScript.Length();
+    TCollection_AsciiString line = theScript.SubString(start, end);
+    bool found = false;
+    for (std::list<TCollection_AsciiString>::const_iterator it = ToRemove.begin(); it != ToRemove.end() && !found; ++it)
+      found = line.Search( *it ) != -1;
+    if (!found)
+      output += line;
+    start = end + 1;
+  }
+  theScript = output;
+
+  //OK @@@@@@@@@@@@@@@@@@@@@@@@@@@
+}
+
 //================================================================================
 /*!
  * \brief Constructor