Salome HOME
Revert "EDF 25230 - Impossible to create directly a face"
[modules/geom.git] / src / XAOPlugin / XAOPlugin_IOperations.cxx
index a2eae44dbd732679515f5ab1e873f8d6c1687578..ec9b8e487ef70c6c9458bd3674683bed9e288b25 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2014-2024  CEA, EDF, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include "XAOPlugin_IImportExport.hxx"
 
 // KERNEL includes
+#include <Basics_DirUtils.hxx>
 #include <utilities.h>
 #include <Utils_SALOME_Exception.hxx>
 
 // GEOM includes
-#include "GEOM_PythonDump.hxx"
-#include "GEOMImpl_Types.hxx"
-#include "GEOMImpl_IGroupOperations.hxx"
-#include "GEOMImpl_IShapesOperations.hxx"
-#include "GEOMImpl_IFieldOperations.hxx"
-#include "GEOM_ISubShape.hxx"
+#include <GEOM_PythonDump.hxx>
+#include <GEOMImpl_Types.hxx>
+#include <GEOMImpl_IGroupOperations.hxx>
+#include <GEOMImpl_IShapesOperations.hxx>
+#include <GEOMImpl_IFieldOperations.hxx>
+#include <GEOM_ISubShape.hxx>
+#include <GEOM_Object.hxx>
+#include <GEOM_Field.hxx>
 
 #include <XAO_Geometry.hxx>
 #include <XAO_BrepGeometry.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
 // OCC includes
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
 #include <TColStd_HArray1OfByte.hxx>
 #include <TColStd_HArray1OfReal.hxx>
-#else
-#include <TDataStd_HArray1OfByte.hxx>
-#endif
 #include <TDataStd_Integer.hxx>
 
+#include <TopExp.hxx>
+
+#include <algorithm>
 
 XAO::Dimension shapeEnumToDimension(const TopAbs_ShapeEnum& shape)
 {
@@ -101,8 +103,8 @@ TopAbs_ShapeEnum getGroupDimension(XAO::Group* group)
  *  Constructor
  */
 //=============================================================================
-XAOPlugin_IOperations::XAOPlugin_IOperations( GEOM_Engine* theEngine, int theDocID )
-: GEOMImpl_IBaseIEOperations( theEngine, theDocID )
+XAOPlugin_IOperations::XAOPlugin_IOperations( GEOM_Engine* theEngine )
+: GEOMImpl_IBaseIEOperations( theEngine )
 {
   MESSAGE( "XAOPlugin_IOperations::XAOPlugin_IOperations" );
 }
@@ -117,21 +119,28 @@ XAOPlugin_IOperations::~XAOPlugin_IOperations()
   MESSAGE( "XAOPlugin_IOperations::~XAOPlugin_IOperations" );
 }
 
-void XAOPlugin_IOperations::exportGroups( std::list<Handle(GEOM_Object)> groupList,
-                                                  XAO::Xao* xaoObject,
-                                                  XAO::BrepGeometry* geometry )
+bool XAOPlugin_IOperations::exportGroups( std::list<Handle(GEOM_Object)> groupList,
+                                          XAO::Xao* xaoObject,
+                                          XAO::BrepGeometry* geometry )
 {
   // add the groups
   std::list<Handle(GEOM_Object)>::iterator groupIterator = groupList.begin();
   while (groupIterator != groupList.end())
   {
     Handle(GEOM_Object) currGroup = (*groupIterator++);
+    if (currGroup->GetType() != GEOM_GROUP) {
+      SetErrorCode("Error when export groups: you could perform this operation only with group.");
+      return false;
+    }
     Handle(TColStd_HArray1OfInteger) groupIds = myGroupOperations->GetObjects(currGroup);
 
     TopAbs_ShapeEnum shapeGroup = myGroupOperations->GetType(currGroup);
     XAO::Dimension dim = shapeEnumToDimension(shapeGroup);
     XAO::Group* group = xaoObject->addGroup(dim, currGroup->GetName().ToCString());
 
+    // Group can be empty
+    if (groupIds.IsNull()) continue;
+
     switch (shapeGroup)
     {
     case TopAbs_VERTEX:
@@ -166,13 +175,16 @@ void XAOPlugin_IOperations::exportGroups( std::list<Handle(GEOM_Object)> groupLi
         group->add(index);
       }
       break;
+    default:
+      ;
     }
   }
+  return true;
 }
 
 void XAOPlugin_IOperations::exportFields( std::list<Handle(GEOM_Field)> fieldList,
-                                                  XAO::Xao* xaoObject,
-                                                  XAO::BrepGeometry* geometry )
+                                          XAO::Xao* xaoObject,
+                                          XAO::BrepGeometry* /*geometry*/ )
 {
   std::list<Handle(GEOM_Field)>::iterator fieldIterator = fieldList.begin();
   while (fieldIterator != fieldList.end())
@@ -262,8 +274,15 @@ void XAOPlugin_IOperations::exportFields( std::list<Handle(GEOM_Field)> fieldLis
 
 void XAOPlugin_IOperations::exportSubshapes( const Handle(GEOM_Object)& shape, XAO::BrepGeometry* geometry )
 {
-  Handle(TColStd_HSequenceOfTransient) subObjects = myShapesOperations->GetExistingSubObjects( shape, false );
+  Handle(TColStd_HSequenceOfTransient) subObjects = myShapesOperations->GetExistingSubObjects( shape, GEOMImpl_IShapesOperations::SubShapes );
   int nbSubObjects = subObjects->Length();
+  if (!nbSubObjects) return;
+
+  TopoDS_Shape aMainShape = shape->GetValue();
+  if (aMainShape.IsNull()) return;
+  TopTools_IndexedMapOfShape anIndices;
+  TopExp::MapShapes(aMainShape, anIndices);
+
   // set the names of the sub shapes
   for (int i = 1; i <= nbSubObjects; i++)
   {
@@ -274,8 +293,16 @@ void XAOPlugin_IOperations::exportSubshapes( const Handle(GEOM_Object)& shape, X
     Handle(GEOM_Object) subObject = Handle(GEOM_Object)::DownCast( transientSubObject );
     if (subObject->GetType() != GEOM_GROUP)
     {
-      int subIndex = myShapesOperations->GetSubShapeIndex( shape, subObject );
-      switch (subObject->GetValue().ShapeType())
+      TopoDS_Shape aSubShape = subObject->GetValue();
+      if (aSubShape.IsNull()) continue;
+
+      // Do not call GEOMImpl_IShapesOperations::GetSubShapeIndex() here
+      // for time optimization reason (it invokes TopExp::MapShapes())
+      //int subIndex = myShapesOperations->GetSubShapeIndex( shape, subObject );
+      int subIndex = anIndices.FindIndex(aSubShape);
+      if (!subIndex) continue;
+
+      switch (aSubShape.ShapeType())
       {
       case TopAbs_VERTEX:
         geometry->changeVertexName(subIndex, subObject->GetName().ToCString());
@@ -289,6 +316,8 @@ void XAOPlugin_IOperations::exportSubshapes( const Handle(GEOM_Object)& shape, X
       case TopAbs_SOLID:
         geometry->changeSolidName(subIndex, subObject->GetName().ToCString());
         break;
+      default:
+        ;
       }
     }
   }
@@ -296,35 +325,83 @@ void XAOPlugin_IOperations::exportSubshapes( const Handle(GEOM_Object)& shape, X
 
 //=============================================================================
 /*!
- *  Export a shape to XAO format
- *  \param shape The shape to export
- *  \param groups The list of groups to export
- *  \param fields The list of fields to export
- *  \param fileName The name of the file to exported
- *  \return boolean indicating if export was succeful.
+ *  Export a shape to XAO format file.
+ *  \param shape The shape to export.
+ *  \param groups The list of groups to export.
+ *  \param fields The list of fields to export.
+ *  \param fileName The name of the file to be exported.
+ *  \param shapeFileName The name of the file for shape, if it should be exported separately.
+ *  \return boolean indicating if export was successful.
  */
 //=============================================================================
 bool XAOPlugin_IOperations::ExportXAO( Handle(GEOM_Object) shape,
-                                      std::list<Handle(GEOM_Object)> groupList,
-                                      std::list<Handle(GEOM_Field)> fieldList,
-                                      const char* author,
-                                      const char* fileName )
+                                       std::list<Handle(GEOM_Object)> groupList,
+                                       std::list<Handle(GEOM_Field)> fieldList,
+                                       const char* author,
+                                       const char* fileName,
+                                       const char* shapeFileName )
+{
+  if (!fileName || !strlen(fileName)) {
+    SetErrorCode("Empty file name");
+    return false;
+  }
+
+  exportXAO( shape, groupList, fieldList, author, fileName, shapeFileName );
+  return IsDone();
+}
+
+//=============================================================================
+/*!
+ *  Export a shape to XAO format string.
+ *  \param shape The shape to export.
+ *  \param groups The list of groups to export.
+ *  \param fields The list of fields to export.
+ *  \return The exported string.
+ */
+//=============================================================================
+std::string XAOPlugin_IOperations::ExportXAOMem( Handle(GEOM_Object) shape,
+                                                 std::list<Handle(GEOM_Object)> groupList,
+                                                 std::list<Handle(GEOM_Field)> fieldList,
+                                                 const char* author )
+{
+  std::string anXML = exportXAO( shape, groupList, fieldList, author, NULL, NULL );
+  return anXML;
+}
+
+//=============================================================================
+/*!
+ *  Export a shape to XAO format file or string.
+ *  \param shape The shape to export.
+ *  \param groups The list of groups to export.
+ *  \param fields The list of fields to export.
+ *  \param fileName The name of the file to be exported. If empty, export to string.
+ *  \param shapeFileName The name of the file for shape, if it should be exported separately.
+ *  \return The exported string, if fileName is empty, or empty string.
+ */
+//=============================================================================
+std::string XAOPlugin_IOperations::exportXAO( Handle(GEOM_Object) shape,
+                                              std::list<Handle(GEOM_Object)> groupList,
+                                              std::list<Handle(GEOM_Field)> fieldList,
+                                              const char* author,
+                                              const char* fileName,
+                                              const char* shapeFileName )
 {
   SetErrorCode(KO);
+  std::string anXML ("");
 
-  if (shape.IsNull()) return false;
+  if (shape.IsNull()) return anXML;
 
   // add a new shape function with parameters
   Handle(GEOM_Function) lastFunction = shape->GetLastFunction();
-  if (lastFunction.IsNull()) return false;
+  if (lastFunction.IsNull()) return anXML;
 
   // add a new result object
-  Handle(GEOM_Object) result = GetEngine()->AddObject(GetDocID(), GEOM_IMPORT);
+  Handle(GEOM_Object) result = GetEngine()->AddObject(GEOM_IMPORT);
 
   // add an Export function
   Handle(GEOM_Function) exportFunction = result->AddFunction(XAOPlugin_Driver::GetID(), EXPORT_SHAPE);
-  if (exportFunction.IsNull()) return false;
-  if (exportFunction->GetDriverGUID() != XAOPlugin_Driver::GetID()) return false;
+  if (exportFunction.IsNull()) return anXML;
+  if (exportFunction->GetDriverGUID() != XAOPlugin_Driver::GetID()) return anXML;
 
   // create the XAO object
   XAO::Xao* xaoObject = new XAO::Xao();
@@ -341,15 +418,36 @@ bool XAOPlugin_IOperations::ExportXAO( Handle(GEOM_Object) shape,
   exportSubshapes(shape, geometry);
   xaoObject->setGeometry(geometry);
 
-  exportGroups(groupList, xaoObject, geometry);
+  if (!exportGroups(groupList, xaoObject, geometry)) return anXML;
   exportFields(fieldList, xaoObject, geometry);
 
-  // export the XAO to the file
-  xaoObject->exportXAO(fileName);
+  bool isFile = (fileName && strlen(fileName));
+  if (isFile) {
+    // export the XAO to the file
+    xaoObject->exportXAO(fileName, shapeFileName);
+  }
+  else {
+    // export the XAO to the string
+    anXML = xaoObject->getXML();
+  }
 
   // make a Python command
-  GEOM::TPythonDump pd(exportFunction);
-  pd << "exported = geompy.ExportXAO(" << shape;
+  GEOM::TPythonDump pd (exportFunction);
+  if (isFile) {
+    pd << "exported = geompy.ExportXAO(";
+  }
+  else {
+    if (!shape->GetName().IsEmpty()) {
+      std::string aGeometryNamePy (shape->GetName().ToCString());
+      std::replace(aGeometryNamePy.begin(), aGeometryNamePy.end(), ' ', '_');
+      pd << "aXAOBuff_" << aGeometryNamePy.c_str() << " = geompy.ExportXAOMem(";
+    }
+    else
+      pd << "aXAOBuff = geompy.ExportXAOMem(";
+  }
+
+  // shape
+  pd << shape;
 
   // list of groups
   pd << ", [";
@@ -375,17 +473,29 @@ bool XAOPlugin_IOperations::ExportXAO( Handle(GEOM_Object) shape,
     }
   }
   pd << "], ";
-  pd << "\"" << author << "\", \"" << fileName << "\")";
+
+  // author
+  pd << "\"" << author << "\"";
+
+  // files
+  if (isFile) {
+    std::string convFileName = Kernel_Utils::BackSlashToSlash(fileName);
+    std::string convShapeFileName;
+    if (shapeFileName && strlen(shapeFileName))
+      convShapeFileName = Kernel_Utils::BackSlashToSlash(shapeFileName);
+    pd << ", \"" << convFileName.c_str() << "\", \"" << convShapeFileName.c_str() << "\"";
+  }
+  pd << ")";
 
   SetErrorCode(OK);
   delete xaoObject;
 
-  return true;
+  return anXML;
 }
 
 void XAOPlugin_IOperations::importSubShapes( XAO::Geometry* xaoGeometry,
-                                                     Handle(GEOM_Function) function, int shapeType, int dim,
-                                                     Handle(TColStd_HSequenceOfTransient)& subShapeList )
+                                             Handle(GEOM_Function) function, int shapeType, int dim,
+                                             Handle(TColStd_HSequenceOfTransient)& subShapeList )
 {
   Handle(GEOM_Object) subShape;
   Handle(GEOM_Function) aFunction;
@@ -405,13 +515,16 @@ void XAOPlugin_IOperations::importSubShapes( XAO::Geometry* xaoGeometry,
     anArray = new TColStd_HArray1OfInteger(1, 1);
     anArray->SetValue(1, iref);
 
-    subShape = GetEngine()->AddObject(GetDocID(), GEOM_SUBSHAPE);
+    subShape = GetEngine()->AddObject(GEOM_SUBSHAPE);
     Handle(GEOM_Function) aFunction = subShape->AddFunction(GEOM_Object::GetSubShapeID(), 1);
     if (aFunction.IsNull())
       return;
 
     subShape->SetName(name.c_str());
-    subShape->SetType(shapeType);
+
+    // commented out, as it prevents correct operation information filling
+    // type should be a GEOM_SUBSHAPE
+    //subShape->SetType(shapeType);
 
     GEOM_ISubShape aSSI(aFunction);
     aSSI.SetMainShape(function);
@@ -427,31 +540,84 @@ void XAOPlugin_IOperations::importSubShapes( XAO::Geometry* xaoGeometry,
 
 //=============================================================================
 /*!
- *  Import a shape from XAO format
- *  \param fileName The name of the file to import
- *  \param shape The imported shape
- *  \param subShapes The list of imported groups
- *  \param groups The list of imported groups
- *  \param fields The list of imported fields
- *  \return boolean indicating if import was succeful.
+ *  Import a shape from XAO format file.
+ *  \param fileName The name of the file to import.
+ *  \param shape The imported shape.
+ *  \param subShapes The list of imported sub-shapes.
+ *  \param groups The list of imported groups.
+ *  \param fields The list of imported fields.
+ *  \return boolean indicating if import was successful.
  */
 //=============================================================================
 bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
-                                               Handle(GEOM_Object)& shape,
-                                               Handle(TColStd_HSequenceOfTransient)& subShapes,
-                                               Handle(TColStd_HSequenceOfTransient)& groups,
-                                               Handle(TColStd_HSequenceOfTransient)& fields )
+                                       Handle(GEOM_Object)& shape,
+                                       Handle(TColStd_HSequenceOfTransient)& subShapes,
+                                       Handle(TColStd_HSequenceOfTransient)& groups,
+                                       Handle(TColStd_HSequenceOfTransient)& fields )
+{
+  if (fileName == NULL || !strlen(fileName)) {
+    SetErrorCode("Empty file name");
+  }
+
+  importXAO( fileName, "", shape, subShapes, groups, fields );
+  return IsDone();
+}
+
+//=============================================================================
+/*!
+ *  Import a shape from XAO format string.
+ *  \param theXML The input buffer.
+ *  \param shape The imported shape.
+ *  \param subShapes The list of imported sub-shapes.
+ *  \param groups The list of imported groups.
+ *  \param fields The list of imported fields.
+ *  \return boolean indicating if import was successful.
+ */
+//=============================================================================
+bool XAOPlugin_IOperations::ImportXAOMem( const std::string& theXML,
+                                          Handle(GEOM_Object)& shape,
+                                          Handle(TColStd_HSequenceOfTransient)& subShapes,
+                                          Handle(TColStd_HSequenceOfTransient)& groups,
+                                          Handle(TColStd_HSequenceOfTransient)& fields )
+{
+  importXAO( NULL, theXML, shape, subShapes, groups, fields );
+  return IsDone();
+}
+
+//=============================================================================
+/*!
+ *  Import a shape from XAO format file.
+ *  \param fileName The name of the file to import.
+ *  \param shape The imported shape.
+ *  \param subShapes The list of imported sub-shapes.
+ *  \param groups The list of imported groups.
+ *  \param fields The list of imported fields.
+ *  \return boolean indicating if import was successful.
+ */
+//=============================================================================
+bool XAOPlugin_IOperations::importXAO( const char* fileName,
+                                       const std::string& theXML,
+                                       Handle(GEOM_Object)& shape,
+                                       Handle(TColStd_HSequenceOfTransient)& subShapes,
+                                       Handle(TColStd_HSequenceOfTransient)& groups,
+                                       Handle(TColStd_HSequenceOfTransient)& fields )
 {
   SetErrorCode(KO);
 
-  if (fileName == NULL || groups.IsNull() || fields.IsNull())
+  if (groups.IsNull() || fields.IsNull())
     return false;
 
+  bool isFile = (fileName && strlen(fileName));
+
   // Read the XAO
   XAO::Xao* xaoObject = new XAO::Xao();
   try
   {
-    xaoObject->importXAO(fileName);
+    if (isFile)
+      xaoObject->importXAO(fileName);
+    else {
+     xaoObject->setXML(theXML);
+    }
   }
   catch (XAO::XAO_Exception& exc)
   {
@@ -469,11 +635,20 @@ bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
   }
 
   // create the shape
-  shape = GetEngine()->AddObject(GetDocID(), GEOM_IMPORT);
+  shape = GetEngine()->AddObject(GEOM_IMPORT);
   Handle(GEOM_Function) function = shape->AddFunction(XAOPlugin_Driver::GetID(), IMPORT_SHAPE);
   if (function.IsNull()) return false;
   if (function->GetDriverGUID() != XAOPlugin_Driver::GetID()) return false;
 
+  // Initialize python dimp here to prevent dumping of sub shapes, groups and fields
+  GEOM::TPythonDump pd(function);
+
+  if (isFile)
+    function->SetString( XAOPlugin_Driver::GetFileNameTag(), fileName );
+  else {
+    function->SetString( XAOPlugin_Driver::GetFileNameTag(), "NO, imported from byte array" );
+  }
+
   // set the geometry
   if (xaoGeometry->getFormat() == XAO::BREP)
   {
@@ -503,13 +678,19 @@ bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
 
     // build an array with the indexes of the sub shapes
     int nbElt = xaoGroup->count();
-    Handle(TColStd_HArray1OfInteger) array = new TColStd_HArray1OfInteger(1, nbElt);
-    int j = 0;
-    for (std::set<int>::iterator it = xaoGroup->begin(); it != xaoGroup->end(); ++it)
-    {
-      int index = (*it);
-      std::string ref = xaoGeometry->getElementReference(xaoGroup->getDimension(), index);
-      array->SetValue(++j, XAO::XaoUtils::stringToInt(ref));
+    Handle(TColStd_HArray1OfInteger) array;
+    if (nbElt > 0) {
+      array = new TColStd_HArray1OfInteger(1, nbElt);
+      int j = 0;
+      for (std::set<int>::iterator it = xaoGroup->begin(); it != xaoGroup->end(); ++it) {
+        int index = (*it);
+        std::string ref = xaoGeometry->getElementReference(xaoGroup->getDimension(), index);
+        array->SetValue(++j, XAO::XaoUtils::stringToInt(ref));
+      }
+    }
+    else { // empty group
+      array = new TColStd_HArray1OfInteger(1, 1);
+      array->SetValue(1, -1);
     }
 
     // create the group with the array of sub shapes indexes
@@ -521,8 +702,6 @@ bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
     TDF_Label freeLabel = group->GetFreeLabel();
     TDataStd_Integer::Set(freeLabel, (Standard_Integer) getGroupDimension(xaoGroup));
     groups->Append(group);
-
-    function = group->GetLastFunction();
   }
 
   // create the fields
@@ -623,7 +802,6 @@ bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
   }
 
   // make a Python command
-  GEOM::TPythonDump pd(function);
   pd << "(imported, " << shape << ", ";
 
   // list of sub shapes
@@ -660,8 +838,21 @@ bool XAOPlugin_IOperations::ImportXAO( const char* fileName,
       pd << obj << ((i < nbFields) ? ", " : "");
     }
   }
-  pd << "]";
-  pd << ") = geompy.ImportXAO(\"" << fileName << "\")";
+  pd << "]) = geompy.";
+
+  if (isFile) {
+    std::string convFileName =  Kernel_Utils::BackSlashToSlash( fileName );
+    pd << "ImportXAO(\"" << convFileName.c_str() << "\")";
+  }
+  else {
+    if (!shape->GetName().IsEmpty()) {
+      std::string aGeometryNamePy (shape->GetName().ToCString());
+      std::replace(aGeometryNamePy.begin(), aGeometryNamePy.end(), ' ', '_');
+      pd << "ImportXAOMem(aXAOBuff_" << aGeometryNamePy.c_str() << ")";
+    }
+    else
+      pd << "ImportXAOMem(aXAOBuff)";
+  }
 
   delete xaoObject;
   SetErrorCode(OK);