From 9e9e32f010b4174ecd0ba2b016f14fee16775365 Mon Sep 17 00:00:00 2001 From: jfa Date: Wed, 21 Jun 2023 12:12:34 +0100 Subject: [PATCH] [bos #35140] [EDF] (2023-T1) Memory communication between SHAPER and GEOM --- .../Test/CTestTestfileInstall.cmake | 8 +- src/ConnectorAPI/Test/TestExportXAOMem.py | 108 ++++++++++++++++ src/ConnectorAPI/Test/TestImportXAOMem.py | 117 ++++++++++++++++++ src/ConnectorAPI/Test/tests.set | 9 +- src/ExchangeAPI/CMakeLists.txt | 2 + src/ExchangeAPI/ExchangeAPI_Export.cpp | 95 ++++++++++++-- src/ExchangeAPI/ExchangeAPI_Export.h | 115 ++++++++++------- src/ExchangeAPI/ExchangeAPI_Import.cpp | 74 ++++++++--- src/ExchangeAPI/ExchangeAPI_Import.h | 23 +++- .../ExchangePlugin_ExportFeature.cpp | 47 +++++-- .../ExchangePlugin_ExportFeature.h | 13 +- .../ExchangePlugin_ImportFeature.cpp | 80 +++++++++--- .../ExchangePlugin_ImportFeature.h | 13 +- src/ExchangePlugin/doc/exportFeature.rst | 8 ++ src/ExchangePlugin/doc/importFeature.rst | 17 ++- src/ExchangePlugin/export_widget.xml | 10 ++ src/ExchangePlugin/plugin-Exchange.xml | 60 +++++---- src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.cpp | 37 ++++++ src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.h | 5 + src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.cpp | 43 +++++++ src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.h | 6 + src/ModelAPI/ModelAPI_Feature.cpp | 5 + src/ModelAPI/ModelAPI_Feature.h | 5 +- src/ModuleBase/ModuleBase_WidgetFactory.cpp | 1 + src/PartSet/PartSet_Module.cpp | 27 ++-- src/PythonAPI/model/exchange/__init__.py | 3 +- src/XAO/XAO_XaoExporter.cxx | 4 +- 27 files changed, 777 insertions(+), 158 deletions(-) create mode 100644 src/ConnectorAPI/Test/TestExportXAOMem.py create mode 100644 src/ConnectorAPI/Test/TestImportXAOMem.py diff --git a/src/ConnectorAPI/Test/CTestTestfileInstall.cmake b/src/ConnectorAPI/Test/CTestTestfileInstall.cmake index ed4901cfd..39752fc09 100644 --- a/src/ConnectorAPI/Test/CTestTestfileInstall.cmake +++ b/src/ConnectorAPI/Test/CTestTestfileInstall.cmake @@ -24,8 +24,14 @@ SET(PYTHON_TEST_DRIVER "$ENV{KERNEL_ROOT_DIR}/bin/salome/appliskel/python_test_d SET(TIMEOUT 300) -FOREACH(tfile ${TEST_NAMES}) +FOREACH(tfile ${TEST_NAMES_SPR}) SET(TEST_NAME ${COMPONENT_NAME}_${tfile}) ADD_TEST(${TEST_NAME} python ${PYTHON_TEST_DRIVER} ${TIMEOUT} ${tfile}.py) SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME}") ENDFOREACH() + +FOREACH(tfile ${TEST_NAMES_ADV}) + SET(TEST_NAME ${COMPONENT_NAME}_${tfile}) + ADD_TEST(${TEST_NAME} python ${PYTHON_TEST_DRIVER} ${TIMEOUT} ${tfile}.py) + SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${SALOME_TEST_LABEL_ADV}") +ENDFOREACH() diff --git a/src/ConnectorAPI/Test/TestExportXAOMem.py b/src/ConnectorAPI/Test/TestExportXAOMem.py new file mode 100644 index 000000000..482e37207 --- /dev/null +++ b/src/ConnectorAPI/Test/TestExportXAOMem.py @@ -0,0 +1,108 @@ +# Copyright (C) 2022-2023 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + TestExportXAOMem.py + Unit test of ExchangePlugin_ExportFeature class +""" + +#========================================================================= +# Initialization of the test +#========================================================================= + +import salome +salome.standalone() +salome.salome_init(1) + +import os +import math +import tempfile + +from ModelAPI import * +from GeomAlgoAPI import * +from salome.shaper import model + +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New() + +#========================================================================= +# test Export XAO to memory buffer (bytes array) +#========================================================================= +def testExportXAOMem(): + + model.begin() + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + Box_1 = model.addBox(Part_1_doc, 10, 10, 10) + Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("FACE", "Box_1_1/Top")]) + Box_2 = model.addBox(Part_1_doc, 20, 20, 20) + model.do() + + # Export to memory buffer (bytes array) + Export_buff1 = model.exportToXAOMem(Part_1_doc, model.selection("SOLID", "Box_1_1"), 'XAO') + Export_buff2 = model.exportToXAOMem(Part_1_doc, model.selection("SOLID", "Box_2_1"), 'XAO') + model.end() + + # check buffer length + # export to XAO file and compare size of file and size of buffer + #assert(len(Export_buff1) == 4392) + #assert(len(Export_buff2) == 4287) + with tempfile.TemporaryDirectory() as tmpdirname: + tmpfilename = os.path.join(tmpdirname, "Box.xao") + Export_1 = model.exportToXAO(Part_1_doc, tmpfilename, model.selection("SOLID", "Box_1_1"), 'XAO') + file_stats = os.stat(tmpfilename) + assert(len(Export_buff1) == file_stats.st_size) + + Export_2 = model.exportToXAO(Part_1_doc, tmpfilename, model.selection("SOLID", "Box_2_1"), 'XAO') + file_stats = os.stat(tmpfilename) + assert(len(Export_buff2) == file_stats.st_size) + pass + + # Import to GEOM + (imported1, b1, [], [Group_1], []) = geompy.ImportXAOMem(Export_buff1, theName="Box1") + (imported2, b2, [], [] , []) = geompy.ImportXAOMem(Export_buff2, theName="Box2") + + # Check result 1 + aTol = 1.e-7 + Props = geompy.BasicProperties(b1) + # surface area + aSurface = 600 + assert (math.fabs(Props[1] - aSurface) < aTol), "The surface is wrong: expected = {0}, real = {1}".format(aSurface, Props[1]) + + Props = geompy.BasicProperties(Group_1) + # surface area + aSurface = 100 + assert (math.fabs(Props[1] - aSurface) < aTol), "The surface is wrong: expected = {0}, real = {1}".format(aSurface, Props[1]) + + # Check result 2 + Props = geompy.BasicProperties(b2) + # surface area + aSurface = 2400 + assert (math.fabs(Props[1] - aSurface) < aTol), "The surface is wrong: expected = {0}, real = {1}".format(aSurface, Props[1]) + +if __name__ == '__main__': + #========================================================================= + # Export a shape into XAO memory buffer + #========================================================================= + testExportXAOMem() + #========================================================================= + # End of test + #========================================================================= diff --git a/src/ConnectorAPI/Test/TestImportXAOMem.py b/src/ConnectorAPI/Test/TestImportXAOMem.py new file mode 100644 index 000000000..ea79eadce --- /dev/null +++ b/src/ConnectorAPI/Test/TestImportXAOMem.py @@ -0,0 +1,117 @@ +# Copyright (C) 2022-2023 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + TestImportXAOMem.py + Unit test of ExchangePlugin_ImportFeature class +""" + +#========================================================================= +# Initialization of the test +#========================================================================= + +import salome +salome.standalone() +salome.salome_init(1) + +import os +import math +import tempfile + +from ModelAPI import * +from GeomAPI import * +from GeomAlgoAPI import * +from salome.shaper import model + +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New() + +#========================================================================= +# test Import XAO from memory buffer (bytes array) +#========================================================================= +def testImportXAOMem(): + + # Export from GEOM + Box_1 = geompy.MakeBoxDXDYDZ(10, 10, 10) + Group_1 = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) + geompy.UnionIDs(Group_1, [33]) + geompy.addToStudy( Box_1, 'Box_1_1' ) + geompy.addToStudyInFather( Box_1, Group_1, 'Group_1' ) + + Export_buff = geompy.ExportXAOMem(Box_1, [Group_1], [], "XAO") + + # check buffer length + # export to XAO file and compare size of file and size of buffer + #assert(len(Export_buff) == 4392) + with tempfile.TemporaryDirectory() as tmpdirname: + tmpfilename = os.path.join(tmpdirname, "Box.xao") + exported = geompy.ExportXAO(Box_1, [Group_1], [], "XAO", tmpfilename, "") + file_stats = os.stat(tmpfilename) + print(file_stats.st_size) + assert(len(Export_buff) == file_stats.st_size) + pass + + # Import to SHAPER + model.begin() + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + + Import_1 = model.addImportXAOMem(Part_1_doc, Export_buff) + model.do() + Import_1.subFeature(0).setName("Group_1") + Import_1.subFeature(0).result().setName("Group_1") + Import_1.setName("Box_1") + Import_1.result().setName("Box_1_1") + + model.end() + + # Check result + assert(Import_1.feature().error() == "") + model.testNbResults(Import_1, 1) + model.testNbSubResults(Import_1, [0]) + model.testNbSubShapes(Import_1, GeomAPI_Shape.SOLID, [1]) + model.testNbSubShapes(Import_1, GeomAPI_Shape.FACE, [6]) + model.testNbSubShapes(Import_1, GeomAPI_Shape.EDGE, [24]) + model.testNbSubShapes(Import_1, GeomAPI_Shape.VERTEX, [48]) + model.testResultsVolumes(Import_1, [1000]) + model.testResultsAreas(Import_1, [600]) + + # check groups are the same in both parts + assert(Part_1_doc.size("Groups") == 1) + res1 = objectToResult(Part_1_doc.object("Groups", 0)) + assert(res1 is not None) + res1It = GeomAPI_ShapeExplorer(res1.shape(), GeomAPI_Shape.FACE) + assert(res1It.more()) + shape1 = res1It.current() + res1It.next() + assert(not res1It.more()) + p1 = res1.shape().middlePoint() + aTol = 1.e-7 + assert(math.fabs(p1.x() - 5) <= aTol and math.fabs(p1.y() - 5) <= aTol and math.fabs(p1.z() - 10) <= aTol), "({}, {}, {}) != ({}, {}, {})".format(p1.x(), p1.y(), p1.z(), 5, 5, 10) + +if __name__ == '__main__': + #========================================================================= + # Import a shape from XAO memory buffer + #========================================================================= + testImportXAOMem() + #========================================================================= + # End of test + #========================================================================= diff --git a/src/ConnectorAPI/Test/tests.set b/src/ConnectorAPI/Test/tests.set index a42f17c80..ecfb7de75 100755 --- a/src/ConnectorAPI/Test/tests.set +++ b/src/ConnectorAPI/Test/tests.set @@ -17,7 +17,7 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -SET(TEST_NAMES +SET(TEST_NAMES_SPR TestExportToGEOM TestExportToGEOMAllGroupsAndFields TestExportToGEOMPartSet @@ -31,3 +31,10 @@ SET(TEST_NAMES TestImportSTL TestImportSTEP ) + +SET(TEST_NAMES_ADV + TestExportXAOMem + TestImportXAOMem +) + +set(TEST_NAMES ${TEST_NAMES_SPR} ${TEST_NAMES_ADV}) diff --git a/src/ExchangeAPI/CMakeLists.txt b/src/ExchangeAPI/CMakeLists.txt index 736d7b062..38506bea9 100644 --- a/src/ExchangeAPI/CMakeLists.txt +++ b/src/ExchangeAPI/CMakeLists.txt @@ -32,6 +32,7 @@ SET(PROJECT_SOURCES ) SET(PROJECT_LIBRARIES + Locale ModelAPI ModelHighAPI GeomAlgoAPI @@ -40,6 +41,7 @@ SET(PROJECT_LIBRARIES INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/Events + ${PROJECT_SOURCE_DIR}/src/Locale ${PROJECT_SOURCE_DIR}/src/ModelAPI ${PROJECT_SOURCE_DIR}/src/ModelHighAPI ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI diff --git a/src/ExchangeAPI/ExchangeAPI_Export.cpp b/src/ExchangeAPI/ExchangeAPI_Export.cpp index 8ee3b8bd7..e22ff2255 100644 --- a/src/ExchangeAPI/ExchangeAPI_Export.cpp +++ b/src/ExchangeAPI/ExchangeAPI_Export.cpp @@ -21,6 +21,8 @@ //-------------------------------------------------------------------------------------- #include //-------------------------------------------------------------------------------------- +#include +//-------------------------------------------------------------------------------------- #include #include #include @@ -28,6 +30,8 @@ #include #include //-------------------------------------------------------------------------------------- +#include +//-------------------------------------------------------------------------------------- ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& theFeature) : ModelHighAPI_Interface(theFeature) @@ -97,11 +101,12 @@ ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& apply(); // finish operation to make sure the export is done on the current state of the history } - - +/// Constructor with values for XAO of selected result export. ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& theFeature, - const std::string & theFilePath, const ModelHighAPI_Selection& theResult, - const std::string & theAuthor, const std::string & theGeometryName) + const std::string & theFilePath, + const ModelHighAPI_Selection& theResult, + const std::string & theAuthor, + const std::string & theGeometryName) : ModelHighAPI_Interface(theFeature) { initialize(); @@ -119,7 +124,26 @@ ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& apply(); // finish operation to make sure the export is done on the current state of the history } - +/// Constructor with values for XAO of selected result export to memory buffer. +ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theResult, + const std::string & theAuthor, + const std::string & theGeometryName) + : ModelHighAPI_Interface(theFeature) +{ + initialize(); + fillAttribute("XAOMem", theFeature->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID())); + fillAttribute(theAuthor, theFeature->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID())); + fillAttribute(theGeometryName, + theFeature->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())); + fillAttribute("XAO", theFeature->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID())); + std::list aListOfOneSel; + aListOfOneSel.push_back(theResult); + fillAttribute(aListOfOneSel, + theFeature->selectionList(ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID())); + execute(true); + apply(); // finish operation to make sure the export is done on the current state of the history +} /// Constructor with values for export in other formats than XAO. ExchangeAPI_Export::ExchangeAPI_Export(const std::shared_ptr& theFeature, @@ -167,13 +191,46 @@ void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const FeaturePtr aBase = feature(); const std::string& aDocName = theDumper.name(aBase->document()); - theDumper << aBase << " = model."; - std::string exportType = aBase->string(ExchangePlugin_ExportFeature::EXPORT_TYPE_ID())->value(); + if (exportType == "XAOMem") { + std::string aGeometryName = + aBase->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->value(); + + theDumper << "aXAOBuff"; + std::string aGeometryNamePy; + if (! aGeometryName.empty()) { + aGeometryNamePy = aGeometryName; + } + else { + aGeometryNamePy = Locale::Convert::toString(aBase->data()->name()); + } + if (! aGeometryNamePy.empty()) { + // add shape name + std::replace(aGeometryNamePy.begin(), aGeometryNamePy.end(), ' ', '_'); + theDumper << "_" << aGeometryNamePy; + } + theDumper << " = model.exportToXAOMem(" << aDocName; + AttributeSelectionListPtr aShapeSelected = + aBase->selectionList(ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID()); + if (aShapeSelected->isInitialized() && aShapeSelected->size() == 1) { + theDumper << ", " << aShapeSelected->value(0); + } + + std::string theAuthor = aBase->string(ExchangePlugin_ExportFeature::XAO_AUTHOR_ID())->value(); + if (! theAuthor.empty()) + theDumper << ", '" << theAuthor << "'"; + if (! aGeometryName.empty()) + theDumper << ", '" << aGeometryName << "'"; + theDumper << ")" << std::endl; + return; + } + + theDumper << aBase << " = model."; + if (exportType == "XAO") { std::string aTmpXAOFile = - aBase->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID())->value(); + aBase->string(ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID())->value(); correctSeparators(aTmpXAOFile); theDumper << "exportToXAO(" << aDocName << ", '" << aTmpXAOFile << "'" ; AttributeSelectionListPtr aShapeSelected = @@ -186,7 +243,7 @@ void ExchangeAPI_Export::dump(ModelHighAPI_Dumper& theDumper) const if (! theAuthor.empty()) theDumper << ", '" << theAuthor << "'"; std::string theGeometryName = - aBase->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->value(); + aBase->string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->value(); if (! theGeometryName.empty()) theDumper << ", '" << theGeometryName << "'"; theDumper << ")" << std::endl; @@ -276,8 +333,10 @@ ExportPtr exportToSTL(const std::shared_ptr & thePart, } ExportPtr exportToXAO(const std::shared_ptr & thePart, - const std::string & theFilePath, const ModelHighAPI_Selection& theSelectedShape, - const std::string & /*theAuthor*/, const std::string & /*theGeometryName*/) + const std::string & theFilePath, + const ModelHighAPI_Selection& theSelectedShape, + const std::string & /*theAuthor*/, + const std::string & /*theGeometryName*/) { apply(); // finish previous operation to make sure all previous operations are done std::shared_ptr aFeature = @@ -286,6 +345,20 @@ ExportPtr exportToXAO(const std::shared_ptr & thePart, return ExportPtr(new ExchangeAPI_Export(aFeature, theFilePath, theSelectedShape, "XAO")); } +PyObject* exportToXAOMem(const std::shared_ptr & thePart, + const ModelHighAPI_Selection& theSelectedShape, + const std::string & theAuthor, + const std::string & theGeometryName) +{ + apply(); // finish previous operation to make sure all previous operations are done + std::shared_ptr aFeature = + thePart->addFeature(ExchangePlugin_ExportFeature::ID()); + ExportPtr aXAOExportAPI (new ExchangeAPI_Export + (aFeature, theSelectedShape, theAuthor, theGeometryName)); + std::string aBuff = aFeature->string(ExchangePlugin_ExportFeature::MEMORY_BUFFER_ID())->value(); + return PyBytes_FromString(aBuff.c_str()); +} + void exportPart(const std::shared_ptr & thePart, const std::string & theFilePath, const std::list & theSelected) diff --git a/src/ExchangeAPI/ExchangeAPI_Export.h b/src/ExchangeAPI/ExchangeAPI_Export.h index d948c8376..c23bc9e66 100644 --- a/src/ExchangeAPI/ExchangeAPI_Export.h +++ b/src/ExchangeAPI/ExchangeAPI_Export.h @@ -30,6 +30,9 @@ #include #include + +#include + //-------------------------------------------------------------------------------------- class ModelHighAPI_Selection; class ModelHighAPI_Double; @@ -55,21 +58,28 @@ public: /// Constructor with values for STL of selected result export. EXCHANGEAPI_EXPORT - explicit ExchangeAPI_Export(const std::shared_ptr& theFeature, - const std::string & theFilePath, - const ModelHighAPI_Selection& theSelectedShape, - const ModelHighAPI_Double& theDeflectionRelative , - const ModelHighAPI_Double& theDeflectionAbsolute, - const bool theIsRelative, - const bool theIsASCII); + explicit ExchangeAPI_Export(const std::shared_ptr& theFeature, + const std::string & theFilePath, + const ModelHighAPI_Selection& theSelectedShape, + const ModelHighAPI_Double& theDeflectionRelative , + const ModelHighAPI_Double& theDeflectionAbsolute, + const bool theIsRelative, + const bool theIsASCII); /// Constructor with values for XAO of selected result export. EXCHANGEAPI_EXPORT - explicit ExchangeAPI_Export(const std::shared_ptr& theFeature, - const std::string & theFilePath, - const ModelHighAPI_Selection& theResult, - const std::string & theAuthor, - const std::string & theGeometryName = std::string()); + explicit ExchangeAPI_Export(const std::shared_ptr& theFeature, + const std::string & theFilePath, + const ModelHighAPI_Selection& theResult, + const std::string & theAuthor, + const std::string & theGeometryName = std::string()); + + /// Constructor with values for XAO of selected result export to memory buffer. + EXCHANGEAPI_EXPORT + explicit ExchangeAPI_Export(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theResult, + const std::string & theAuthor, + const std::string & theGeometryName = std::string()); /// Constructor with values for export in other formats than XAO. EXCHANGEAPI_EXPORT @@ -82,39 +92,41 @@ public: EXCHANGEAPI_EXPORT virtual ~ExchangeAPI_Export(); - INTERFACE_15(ExchangePlugin_ExportFeature::ID(), - exportType, ExchangePlugin_ExportFeature::EXPORT_TYPE_ID(), - ModelAPI_AttributeString, /** ExportType */, - filePath, ExchangePlugin_ExportFeature::FILE_PATH_ID(), - ModelAPI_AttributeString, /** file path */, - xaoFilePath, ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID(), - ModelAPI_AttributeString, /** xao_file_path */, - fileFormat, ExchangePlugin_ExportFeature::FILE_FORMAT_ID(), - ModelAPI_AttributeString, /** file format */, - selectionList, ExchangePlugin_ExportFeature::SELECTION_LIST_ID(), - ModelAPI_AttributeString, /** selection list */, - xaoAuthor, ExchangePlugin_ExportFeature::XAO_AUTHOR_ID(), - ModelAPI_AttributeString, /** xao author */, - xaoGeometryName, ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID(), - ModelAPI_AttributeString, /** xao geometry name */, - stlFilePath, ExchangePlugin_ExportFeature::STL_FILE_PATH_ID(), - ModelAPI_AttributeString, /** stl_file_path */, - stlobjectselected, ExchangePlugin_ExportFeature::STL_OBJECT_SELECTED(), - ModelAPI_AttributeSelection, /** Object selected to export in stl file*/, - stldeflectionType, ExchangePlugin_ExportFeature::STL_DEFLECTION_TYPE(), - ModelAPI_AttributeString, /** Type of the defelection */, - stlrelative, ExchangePlugin_ExportFeature::STL_RELATIVE(), - ModelAPI_AttributeDouble, /** Relative*/, - stlabsolute, ExchangePlugin_ExportFeature::STL_ABSOLUTE(), - ModelAPI_AttributeDouble, /** Absolute */, - stlfileType, ExchangePlugin_ExportFeature::STL_FILE_TYPE(), - ModelAPI_AttributeString, /** Type of the stl file*/, - stldeflectionTypeabsolute, + INTERFACE_16(ExchangePlugin_ExportFeature::ID(), + exportType, ExchangePlugin_ExportFeature::EXPORT_TYPE_ID(), + ModelAPI_AttributeString, /** ExportType */, + filePath, ExchangePlugin_ExportFeature::FILE_PATH_ID(), + ModelAPI_AttributeString, /** file path */, + xaoFilePath, ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID(), + ModelAPI_AttributeString, /** xao_file_path */, + fileFormat, ExchangePlugin_ExportFeature::FILE_FORMAT_ID(), + ModelAPI_AttributeString, /** file format */, + selectionList, ExchangePlugin_ExportFeature::SELECTION_LIST_ID(), + ModelAPI_AttributeString, /** selection list */, + xaoAuthor, ExchangePlugin_ExportFeature::XAO_AUTHOR_ID(), + ModelAPI_AttributeString, /** xao author */, + xaoGeometryName, ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID(), + ModelAPI_AttributeString, /** xao geometry name */, + stlFilePath, ExchangePlugin_ExportFeature::STL_FILE_PATH_ID(), + ModelAPI_AttributeString, /** stl_file_path */, + stlobjectselected, ExchangePlugin_ExportFeature::STL_OBJECT_SELECTED(), + ModelAPI_AttributeSelection, /** Object selected to export in stl file*/, + stldeflectionType, ExchangePlugin_ExportFeature::STL_DEFLECTION_TYPE(), + ModelAPI_AttributeString, /** Type of the defelection */, + stlrelative, ExchangePlugin_ExportFeature::STL_RELATIVE(), + ModelAPI_AttributeDouble, /** Relative*/, + stlabsolute, ExchangePlugin_ExportFeature::STL_ABSOLUTE(), + ModelAPI_AttributeDouble, /** Absolute */, + stlfileType, ExchangePlugin_ExportFeature::STL_FILE_TYPE(), + ModelAPI_AttributeString, /** Type of the stl file*/, + stldeflectionTypeabsolute, ExchangePlugin_ExportFeature::STL_DEFLECTION_TYPE_ABSOLUTE(), - ModelAPI_AttributeString, /** Type of the defelection */, - stldeflectionTyperelative, + ModelAPI_AttributeString, /** Type of the defelection */, + stldeflectionTyperelative, ExchangePlugin_ExportFeature::STL_DEFLECTION_TYPE_RELATIVE(), - ModelAPI_AttributeString, /** Type of the defelection */) + ModelAPI_AttributeString, /** Type of the defelection */, + memoryBuff, ExchangePlugin_ExportFeature::MEMORY_BUFFER_ID(), + ModelAPI_AttributeString, /** Bytes*/) /// Dump wrapped feature EXCHANGEAPI_EXPORT @@ -159,10 +171,19 @@ ExportPtr exportToSTL(const std::shared_ptr & thePart, */ EXCHANGEAPI_EXPORT ExportPtr exportToXAO(const std::shared_ptr & thePart, - const std::string & theFilePath, - const ModelHighAPI_Selection& theSelectedShape, - const std::string & theAuthor = std::string(), - const std::string & theGeometryName = std::string()); + const std::string & theFilePath, + const ModelHighAPI_Selection& theSelectedShape, + const std::string & theAuthor = std::string(), + const std::string & theGeometryName = std::string()); + +/**\ingroup CPPHighAPI +* \brief Exports to XAO format buffer the selected result with groups parts related to it only. +*/ +EXCHANGEAPI_EXPORT +PyObject* exportToXAOMem(const std::shared_ptr & thePart, + const ModelHighAPI_Selection& theSelectedShape, + const std::string & theAuthor = std::string(), + const std::string & theGeometryName = std::string()); /** \ingroup CPPHighAPI diff --git a/src/ExchangeAPI/ExchangeAPI_Import.cpp b/src/ExchangeAPI/ExchangeAPI_Import.cpp index d29f7b2d2..09df54f08 100644 --- a/src/ExchangeAPI/ExchangeAPI_Import.cpp +++ b/src/ExchangeAPI/ExchangeAPI_Import.cpp @@ -21,6 +21,8 @@ //-------------------------------------------------------------------------------------- #include //-------------------------------------------------------------------------------------- +#include +//-------------------------------------------------------------------------------------- #include #include #include @@ -54,6 +56,19 @@ ExchangeAPI_Import::ExchangeAPI_Import( setFilePath(theFilePath); } +ExchangeAPI_Import::ExchangeAPI_Import( + const std::shared_ptr & theFeature, + const std::string & /*theFilePath*/, + const std::string & theBuffer) +: ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute("XAOMem", myimportType); + fillAttribute(theBuffer, mymemoryBuffer); + execute(); + } +} + ExchangeAPI_Import::ExchangeAPI_Import( const std::shared_ptr & theFeature, const std::string & theFilePath, @@ -106,35 +121,48 @@ void ExchangeAPI_Import::dump(ModelHighAPI_Dumper& theDumper) const std::string aPartName = theDumper.name(aBase->document()); AttributeStringPtr aImportTypeAttr = - aBase->string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID()); + aBase->string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID()); std::string aFormat = aImportTypeAttr->value(); - std::string aFilePath; - if (aFormat == "STEP" || aFormat == "STP") - { - aFilePath = aBase->string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID())->value(); - } else { - aFilePath = aBase->string(ExchangePlugin_ImportFeature::FILE_PATH_ID())->value(); - } - std::string aFrom = "\\"; - std::string aTo = "\\\\"; - for(std::size_t aPos = aFilePath.find(aFrom); - aPos != std::string::npos; - aPos = aFilePath.find(aFrom, aPos)) { - aFilePath.replace(aPos, aFrom.size(), aTo); - aPos += aTo.size(); + if (aFormat == "XAOMem") { + theDumper << aBase << " = model.addImportXAOMem(" << aPartName << ", aXAOBuff"; + std::string aGeometryNamePy = Locale::Convert::toString(aBase->data()->name()); + if (! aGeometryNamePy.empty()) { + // add shape name + std::replace(aGeometryNamePy.begin(), aGeometryNamePy.end(), ' ', '_'); + theDumper << "_" << aGeometryNamePy; + } + theDumper << ")" << std::endl; } - std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(aFilePath); - if (anExtension == "STP" || anExtension == "STEP"){ + else { + std::string aFilePath; + if (aFormat == "STEP" || aFormat == "STP") { + aFilePath = aBase->string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID())->value(); + } else { + aFilePath = aBase->string(ExchangePlugin_ImportFeature::FILE_PATH_ID())->value(); + } + + std::string aFrom = "\\"; + std::string aTo = "\\\\"; + for (std::size_t aPos = aFilePath.find(aFrom); + aPos != std::string::npos; + aPos = aFilePath.find(aFrom, aPos)) { + aFilePath.replace(aPos, aFrom.size(), aTo); + aPos += aTo.size(); + } + std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(aFilePath); + if (anExtension == "STP" || anExtension == "STEP") { theDumper << aBase << " = model.addImportSTEP(" << aPartName << ", \"" << aFilePath << "\"" ; theDumper << ", " << scalInterUnits()->value() << ", " << materials()->value() << ", " << colors()->value() << ")"<< std::endl; - } else { + } + else { theDumper << aBase << " = model.addImport(" << aPartName << ", \"" - << aFilePath << "\")" << std::endl; + << aFilePath << "\")" << std::endl; + } } // to make import have results @@ -161,6 +189,14 @@ ImportPtr addImport( return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath)); } +ImportPtr addImportXAOMem(const std::shared_ptr & thePart, + PyObject* theBuffer) +{ + std::shared_ptr aFeature = thePart->addFeature(ExchangeAPI_Import::ID()); + std::string aString (PyBytes_AsString(theBuffer)); + return ImportPtr(new ExchangeAPI_Import(aFeature, "", aString)); +} + ImportPtr addImportSTEP( const std::shared_ptr & thePart, const std::string & theFilePath, diff --git a/src/ExchangeAPI/ExchangeAPI_Import.h b/src/ExchangeAPI/ExchangeAPI_Import.h index cd8d21b61..76262f8e3 100644 --- a/src/ExchangeAPI/ExchangeAPI_Import.h +++ b/src/ExchangeAPI/ExchangeAPI_Import.h @@ -31,7 +31,10 @@ #include #include #include + +#include //-------------------------------------------------------------------------------------- + /**\class ExchangeAPI_Import * \ingroup CPPHighAPI * \brief Interface for Import feature @@ -42,11 +45,18 @@ public: /// Constructor without values EXCHANGEAPI_EXPORT explicit ExchangeAPI_Import(const std::shared_ptr & theFeature); + /// Constructor with values EXCHANGEAPI_EXPORT ExchangeAPI_Import(const std::shared_ptr & theFeature, const std::string & theFilePath); + /// Constructor with values for XAO import from memory buffer + EXCHANGEAPI_EXPORT + ExchangeAPI_Import(const std::shared_ptr & theFeature, + const std::string & theFilePath, + const std::string & theBuffer); + /// Constructor with values for Step file EXCHANGEAPI_EXPORT ExchangeAPI_Import(const std::shared_ptr & theFeature, @@ -58,7 +68,7 @@ public: EXCHANGEAPI_EXPORT virtual ~ExchangeAPI_Import(); - INTERFACE_6(ExchangePlugin_ImportFeature::ID(), + INTERFACE_7(ExchangePlugin_ImportFeature::ID(), filePath, ExchangePlugin_ImportFeature::FILE_PATH_ID(), ModelAPI_AttributeString, /** File path */, importType, ExchangePlugin_ImportFeature::IMPORT_TYPE_ID(), @@ -70,7 +80,9 @@ public: materials, ExchangePlugin_ImportFeature::STEP_MATERIALS_ID(), ModelAPI_AttributeBoolean, /** Materials */, colors, ExchangePlugin_ImportFeature::STEP_COLORS_ID(), - ModelAPI_AttributeBoolean, /** Colors */ + ModelAPI_AttributeBoolean, /** Colors */, + memoryBuffer, ExchangePlugin_ImportFeature::MEMORY_BUFFER_ID(), + ModelAPI_AttributeString, /** Bytes */ ) /// Set point values @@ -98,6 +110,13 @@ EXCHANGEAPI_EXPORT ImportPtr addImport(const std::shared_ptr & thePart, const std::string & theFilePath); +/**\ingroup CPPHighAPI + * \brief Create Import feature to import XAO data from bytes buffer + */ +EXCHANGEAPI_EXPORT +ImportPtr addImportXAOMem(const std::shared_ptr & thePart, + PyObject* theBuffer); + /**\ingroup CPPHighAPI * \brief Create Import Step feature */ diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp index b04aaaed5..ca1a2e4dd 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,10 @@ void ExchangePlugin_ExportFeature::initAttributes() data()->addAttribute(ExchangePlugin_ExportFeature::STL_FILE_TYPE(), ModelAPI_AttributeString::typeId()); + // export to memory buffer (implemented for XAO format only) + data()->addAttribute(ExchangePlugin_ExportFeature::MEMORY_BUFFER_ID(), + ModelAPI_AttributeString::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ExchangePlugin_ExportFeature::XAO_FILE_PATH_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), @@ -127,11 +132,14 @@ void ExchangePlugin_ExportFeature::initAttributes() ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ExchangePlugin_ExportFeature::XAO_SELECTION_LIST_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), + ExchangePlugin_ExportFeature::MEMORY_BUFFER_ID()); // to support previous version of document, move the selection list // if the type of export operation is XAO AttributeStringPtr aTypeAttr = string(EXPORT_TYPE_ID()); - if (aTypeAttr->isInitialized() && aTypeAttr->value() == "XAO") { + if (aTypeAttr->isInitialized() && + (aTypeAttr->value() == "XAO" || aTypeAttr->value() == "XAOMem")) { bool aWasBlocked = data()->blockSendAttributeUpdated(true, false); AttributeSelectionListPtr aSelList = selectionList(SELECTION_LIST_ID()); AttributeSelectionListPtr aXAOSelList = selectionList(XAO_SELECTION_LIST_ID()); @@ -163,21 +171,29 @@ void ExchangePlugin_ExportFeature::execute() this->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID()); std::string aFormat = aFormatAttr->value(); + bool isMemoryExport = false; + AttributeStringPtr aTypeAttr = string(EXPORT_TYPE_ID()); + if (aTypeAttr->isInitialized() && aTypeAttr->value() == "XAOMem") + isMemoryExport = true; + AttributeStringPtr aFilePathAttr = this->string(ExchangePlugin_ExportFeature::FILE_PATH_ID()); std::string aFilePath = aFilePathAttr->value(); - if (aFilePath.empty()) + if (aFilePath.empty() && !isMemoryExport) return; - exportFile(aFilePath, aFormat); + exportFile(aFilePath, aFormat, isMemoryExport); } void ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName, - const std::string& theFormat) + const std::string& theFormat, + const bool isMemoryExport) { std::string aFormatName = theFormat; if (aFormatName.empty()) { // get default format for the extension + if (isMemoryExport) return; + // ".brep" -> "BREP" std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(theFileName); if (anExtension == "BREP" || anExtension == "BRP") { @@ -192,9 +208,9 @@ void ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName, } if (aFormatName == "XAO") { - exportXAO(theFileName); + exportXAO(theFileName, isMemoryExport); return; - }else if (aFormatName == "STL") { + } else if (aFormatName == "STL") { exportSTL(theFileName); return; } @@ -248,7 +264,8 @@ void ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName, /// Returns XAO string by the value from the table static std::string valToString(const ModelAPI_AttributeTables::Value& theVal, - const ModelAPI_AttributeTables::ValueType& theType) { + const ModelAPI_AttributeTables::ValueType& theType) +{ std::ostringstream aStr; // the resulting string value switch(theType) { case ModelAPI_AttributeTables::BOOLEAN: @@ -309,7 +326,8 @@ void ExchangePlugin_ExportFeature::exportSTL(const std::string& theFileName) } -void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) +void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName, + const bool isMemoryExport) { try { @@ -396,6 +414,12 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) // get the name from the first result ResultPtr aResultBody = *aResults.begin(); aGeometryName = Locale::Convert::toString(aResultBody->data()->name()); + if (isMemoryExport) { + // for python dump + string(ExchangePlugin_ExportFeature::XAO_GEOMETRY_NAME_ID())->setValue(aGeometryName); + // or + //data()->setName(Locale::Convert::toWString(aGeometryName)); + } } aXao.getGeometry()->setName(aGeometryName); @@ -563,7 +587,12 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) } // exporting - XAOExport(theFileName, &aXao, anError); + if (isMemoryExport) { + string(ExchangePlugin_ExportFeature::MEMORY_BUFFER_ID())->setValue(XAOExportMem(&aXao, anError)); + } + else { + XAOExport(theFileName, &aXao, anError); + } if (!anError.empty()) { setError("An error occurred while exporting " + theFileName + ": " + anError); diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.h b/src/ExchangePlugin/ExchangePlugin_ExportFeature.h index 5331b39f4..100a5e00c 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.h +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.h @@ -150,6 +150,13 @@ public: static const std::string MY_XAO_GEOMETRY_NAME_ID("xao_geometry_name"); return MY_XAO_GEOMETRY_NAME_ID; } + /// attribute string memory buffer + inline static const std::string& MEMORY_BUFFER_ID() + { + static const std::string MY_MEMORY_BUFFER_ID("memory_buffer"); + return MY_MEMORY_BUFFER_ID; + } + /// Default constructor EXCHANGEPLUGIN_EXPORT ExchangePlugin_ExportFeature(); /// Default destructor @@ -185,10 +192,12 @@ public: protected: /// Performs export of the file EXCHANGEPLUGIN_EXPORT void exportFile(const std::string& theFileName, - const std::string& theFormat); + const std::string& theFormat, + const bool isMemoryExport); /// Performs export to XAO file - EXCHANGEPLUGIN_EXPORT void exportXAO(const std::string& theFileName); + EXCHANGEPLUGIN_EXPORT void exportXAO(const std::string& theFileName, + const bool isMemoryExport); /// Performs export to STL file EXCHANGEPLUGIN_EXPORT void exportSTL(const std::string& theFileName); diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp index 7020326e7..a57986e32 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp @@ -94,6 +94,7 @@ void ExchangePlugin_ImportFeature::initAttributes() data()->addAttribute(STEP_MATERIALS_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(STEP_COLORS_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(STEP_SCALE_INTER_UNITS_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(MEMORY_BUFFER_ID(), ModelAPI_AttributeString::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory( getKind(), ExchangePlugin_ImportFeature::STEP_COLORS_ID()); @@ -105,7 +106,22 @@ void ExchangePlugin_ImportFeature::initAttributes() getKind(), ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory( getKind(), ExchangePlugin_ImportFeature::FILE_PATH_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory( + getKind(), ExchangePlugin_ImportFeature::MEMORY_BUFFER_ID()); +} + +bool ExchangePlugin_ImportFeature::isEditable() +{ + AttributeStringPtr aImportTypeAttr = string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID()); + std::string aFormat = aImportTypeAttr->value(); + + if (aFormat == "XAOMem") + // If the shape is imported from memory buffer, do not allow to edit the feature + return false; + + return true; } + /* * Computes or recomputes the results */ @@ -113,20 +129,34 @@ void ExchangePlugin_ImportFeature::execute() { AttributeStringPtr aImportTypeAttr = string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID()); std::string aFormat = aImportTypeAttr->value(); - AttributeStringPtr aFilePathAttr; - if (aFormat == "STEP" || aFormat == "STP") - { - aFilePathAttr = string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID()); - } else { - aFilePathAttr = string(ExchangePlugin_ImportFeature::FILE_PATH_ID()); + + if (aFormat == "XAOMem") { + // Import from memory buffer + AttributeStringPtr aMemoryBuffAttr = + string(ExchangePlugin_ImportFeature::MEMORY_BUFFER_ID()); + std::string aMemoryBuff = aMemoryBuffAttr->value(); + if (aMemoryBuff.empty()) { + setError("Memory buffer is empty."); + return; + } + importXAO("", aMemoryBuff, true); } - std::string aFilePath = aFilePathAttr->value(); - if (aFilePath.empty()) { - setError("File path is empty."); - return; + else { + // Import from file + AttributeStringPtr aFilePathAttr; + if (aFormat == "STEP" || aFormat == "STP") { + aFilePathAttr = string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID()); + } + else { + aFilePathAttr = string(ExchangePlugin_ImportFeature::FILE_PATH_ID()); + } + std::string aFilePath = aFilePathAttr->value(); + if (aFilePath.empty()) { + setError("File path is empty."); + return; + } + importFile(aFilePath); } - - importFile(aFilePath); } void ExchangePlugin_Import_ImageFeature::execute() @@ -357,16 +387,26 @@ void ExchangePlugin_ImportFeature::setMaterielGroup( } } -void ExchangePlugin_ImportFeature::importXAO(const std::string& theFileName) +void ExchangePlugin_ImportFeature::importXAO(const std::string& theFileName, + const std::string& theMemoryBuff, + const bool isMemoryImport) { + std::string aDataSource = theFileName; + try { std::string anError; XAO::Xao aXao; - std::shared_ptr aGeomShape = XAOImport(theFileName, anError, &aXao); + std::shared_ptr aGeomShape; + if (isMemoryImport) { + aGeomShape = XAOImportMem(theMemoryBuff, anError, &aXao); + aDataSource = "memory buffer"; + } + else + aGeomShape = XAOImport(theFileName, anError, &aXao); if (!anError.empty()) { - setError("An error occurred while importing " + theFileName + ": " + anError); + setError("An error occurred while importing " + aDataSource + ": " + anError); return; } @@ -374,8 +414,12 @@ void ExchangePlugin_ImportFeature::importXAO(const std::string& theFileName) // use the geometry name or the file name for the feature std::string aBodyName = aXaoGeometry->getName(); - if (aBodyName.empty()) - aBodyName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); + if (aBodyName.empty()) { + if (isMemoryImport) + aBodyName = "ImportXAOMem"; + else + aBodyName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); + } data()->setName(Locale::Convert::toWString(aBodyName)); ResultBodyPtr aResultBody = createResultBody(aGeomShape); @@ -549,7 +593,7 @@ void ExchangePlugin_ImportFeature::importXAO(const std::string& theFileName) // LCOV_EXCL_START } catch (XAO::XAO_Exception& e) { std::string anError = e.what(); - setError("An error occurred while importing " + theFileName + ": " + anError); + setError("An error occurred while importing " + aDataSource + ": " + anError); return; } // LCOV_EXCL_STOP diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.h b/src/ExchangePlugin/ExchangePlugin_ImportFeature.h index 2398b4189..8a47253a3 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportFeature.h +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.h @@ -149,6 +149,12 @@ public: static const std::string MY_STEP_COLORS_ID("step_colors"); return MY_STEP_COLORS_ID; } + /// attribute memory buffer + inline static const std::string& MEMORY_BUFFER_ID() + { + static const std::string MY_MEMORY_BUFFER_ID("memory_buffer"); + return MY_MEMORY_BUFFER_ID; + } /// Returns the unique kind of a feature EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind() override { @@ -161,12 +167,17 @@ public: /// Request for initialization of data model of the feature: adding all attributes EXCHANGEPLUGIN_EXPORT virtual void initAttributes(); + /// Return false in case of XAOMem import. + EXCHANGEPLUGIN_EXPORT virtual bool isEditable(); + protected: /// Performs the import of the file EXCHANGEPLUGIN_EXPORT void importFile(const std::string& theFileName) override; /// Performs the import of XAO file - EXCHANGEPLUGIN_EXPORT void importXAO(const std::string& theFileName); + EXCHANGEPLUGIN_EXPORT void importXAO(const std::string& theFileName, + const std::string& theMemoryBuff = std::string(), + const bool isMemoryImport = false); private: /// Set groups of color diff --git a/src/ExchangePlugin/doc/exportFeature.rst b/src/ExchangePlugin/doc/exportFeature.rst index 1773c9bf9..072c9495a 100644 --- a/src/ExchangePlugin/doc/exportFeature.rst +++ b/src/ExchangePlugin/doc/exportFeature.rst @@ -119,6 +119,14 @@ Selection list in the property panel contains a list of exported objects which c :param string: The name of the author, empty by default :param string: The name for the shape processed in GEOMETRY module, empty by default +.. py:function:: aBuffer = model.exportToXAOMem(Part_doc, Object, Author="", GeometryName="") + + This function enables passing data in XAO format from SHAPER to GEOM through a memory buffer (bytes array), without creation of real file on disk. + + :param object: The object to export + :param string: The name of the author, empty by default + :param string: The name for the shape processed in GEOMETRY module, empty by default + Result """""" diff --git a/src/ExchangePlugin/doc/importFeature.rst b/src/ExchangePlugin/doc/importFeature.rst index 817c5c1cb..f035ea360 100644 --- a/src/ExchangePlugin/doc/importFeature.rst +++ b/src/ExchangePlugin/doc/importFeature.rst @@ -47,10 +47,10 @@ The import will be performed within the active part. If no part is active, the p **TUI Command**: -.. py:function:: model.importPart(Doc, FileNameString, [PrevFeature]) +.. py:function:: model.importPart(Part_doc, FileNameString, [PrevFeature]) - :param part: The current part object - :param string: A file name string + :param Part_doc: The target part document, where to import the data + :param string: The file name string :param reference: The feature after which the imported entities should be inserted @@ -88,9 +88,16 @@ In case of first choice the format of imported file will be defined according to .. py:function:: model.addImport(Part_doc, FileNameString) - :param part: The current part object + :param Part_doc: The target part document, where to import the data :param string: A file name string. +.. py:function:: model.addImportXAOMem(Part_doc, aBuffer) + + This function allows importing data in XAO format from GEOM through a memory buffer (bytes array), without creation of real file on disk. + + :param Part_doc: The target part document, where to import the data + :param aBuffer: A byte array with data in XAO format. + Result """""" @@ -127,7 +134,7 @@ The **Import to** combobox provides the list of destinations (one of existing Pa .. py:function:: model.addImportSTEP(Part_doc, FileNameString,scalInterUnits,materials,colors) - :param part: The current part object + :param Part_doc: The target part document, where to import the data :param string: A file name string. :param boolean: True if scale to UIS :param boolean: True to create groups from materials diff --git a/src/ExchangePlugin/export_widget.xml b/src/ExchangePlugin/export_widget.xml index 83b9aba4d..9eff85040 100644 --- a/src/ExchangePlugin/export_widget.xml +++ b/src/ExchangePlugin/export_widget.xml @@ -31,6 +31,16 @@ placeholder="Please input the geometry name"> + + + + + + - - - + + + - - - - + + + + + string_list_attribute="step_target_parts_list" + label="Import to" + tooltip="Select the part to import the document" /> + label="Scale to International System of Units" + default="true"/> + label="Materials" + default="false"/> + label="Colors" + default="false"/> + + - + + @@ -49,6 +52,7 @@ label="Import to" tooltip="Select the image to import the document" /> + @@ -63,18 +67,20 @@ + label="Scale to International System of Units" + default="true"/> + label="Materials" + default="false"/> + label="Colors" + default="false"/> + + + + diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.cpp index af7a2b131..89f53c637 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.cpp @@ -81,3 +81,40 @@ bool XAOExport(const std::string& theFileName, } return true; } + +//============================================================================= +/*! + * + */ +//============================================================================= +const std::string XAOExportMem(XAO::Xao* theXao, + std::string& theError) +{ + std::string aRetBuff (""); + +#ifdef _DEBUG + std::cout << "Export XAO into memory buffer " << std::endl; +#endif + + if (!theXao) { + theError = "An invalid argument."; + return aRetBuff; + } + + try { + XAO::BrepGeometry* aGeometry = dynamic_cast(theXao->getGeometry()); + TopoDS_Shape aShape = aGeometry->getTopoDS_Shape(); + bool aWasFree = aShape.Free(); // make top level topology free, same as imported + if (!aWasFree) + aShape.Free(Standard_True); + + aRetBuff = XAO::XaoExporter::saveToXml(theXao); + + if (!aWasFree) + aShape.Free(Standard_False); + } catch (XAO::XAO_Exception& e) { + theError = e.what(); + return aRetBuff; + } + return aRetBuff; +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.h b/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.h index 2944b9645..3ae31de6b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_XAOExport.h @@ -42,4 +42,9 @@ bool XAOExport(const std::string& theFileName, XAO::Xao* theXao, std::string& theError); +/// Implementation of the export XAO to memory buffer (std::string) +GEOMALGOAPI_EXPORT +const std::string XAOExportMem(XAO::Xao* theXao, + std::string& theError); + #endif /* GEOMALGOAPI_XAOEXPORT_H_ */ diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.cpp index 2d734e881..5b2414976 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.cpp @@ -66,3 +66,46 @@ std::shared_ptr XAOImport(const std::string& theFileName, aGeomShape->setImpl(new TopoDS_Shape(aShape)); return aGeomShape; } + +//============================================================================= +/*! + * + */ +//============================================================================= +std::shared_ptr XAOImportMem(const std::string& theMemoryBuff, + std::string& theError, + XAO::Xao* theXao) +{ +#ifdef _DEBUG + std::cout << "Import XAO from file " << theFileName << std::endl; +#endif + if (theMemoryBuff.empty() || !theXao) { + theError = "An invalid argument."; + return std::shared_ptr(); + } + + TopoDS_Shape aShape; + try { + if (XAO::XaoExporter::setXML(theMemoryBuff, theXao)) { + XAO::Geometry* aGeometry = theXao->getGeometry(); + XAO::Format aFormat = aGeometry->getFormat(); + if (aFormat == XAO::BREP) { + if (XAO::BrepGeometry* aBrepGeometry = dynamic_cast(aGeometry)) + aShape = aBrepGeometry->getTopoDS_Shape(); + } else { + theError = "Unsupported XAO geometry format:" + XAO::XaoUtils::shapeFormatToString(aFormat); + aShape.Nullify(); + } + } else { + theError = "XAO object was not read successful"; + aShape.Nullify(); + } + } catch (XAO::XAO_Exception& e) { + theError = e.what(); + aShape.Nullify(); + } + + std::shared_ptr aGeomShape(new GeomAPI_Shape); + aGeomShape->setImpl(new TopoDS_Shape(aShape)); + return aGeomShape; +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.h b/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.h index 5682dcf31..986e03cef 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_XAOImport.h @@ -36,4 +36,10 @@ std::shared_ptr XAOImport(const std::string& theFileName, std::string& theError, XAO::Xao* theXao); +/// Implementation of the import XAO data from memory buffer +GEOMALGOAPI_EXPORT +std::shared_ptr XAOImportMem(const std::string& theMemoryBuff, + std::string& theError, + XAO::Xao* theXao); + #endif /* GEOMALGOAPI_XAOIMPORT_H_ */ diff --git a/src/ModelAPI/ModelAPI_Feature.cpp b/src/ModelAPI/ModelAPI_Feature.cpp index 945a0efbd..21370b221 100644 --- a/src/ModelAPI/ModelAPI_Feature.cpp +++ b/src/ModelAPI/ModelAPI_Feature.cpp @@ -253,6 +253,11 @@ bool ModelAPI_Feature::isStable() return myIsStable; } +bool ModelAPI_Feature::isEditable() +{ + return true; +} + bool ModelAPI_Feature::customAction(const std::string& /*theActionId*/) { return false; diff --git a/src/ModelAPI/ModelAPI_Feature.h b/src/ModelAPI/ModelAPI_Feature.h index c5705de11..c973d4464 100644 --- a/src/ModelAPI/ModelAPI_Feature.h +++ b/src/ModelAPI/ModelAPI_Feature.h @@ -41,7 +41,7 @@ class ModelAPI_Feature : public ModelAPI_Object std::list > myResults; ///< is feature disabled or not bool myIsDisabled; - ///< is feature is stable (not editing) + ///< is feature stable (not editing) bool myIsStable; public: @@ -155,6 +155,9 @@ class ModelAPI_Feature : public ModelAPI_Object /// Returns the feature is stable or not. MODELAPI_EXPORT virtual bool isStable(); + /// Returns the feature is editable or not. Most of features are editable. + MODELAPI_EXPORT virtual bool isEditable(); + /// Performs some custom feature specific functionality (normally called by some GUI button) /// \param theActionId an action key /// \return a boolean value about it is performed diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index 4e1e51146..486b44250 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -133,6 +133,7 @@ void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, bool a //it's pages recursively and setup into the widget. if (myWidgetApi->toChildWidget()) { do { + if (myWidgetApi->getBooleanAttribute(ATTR_INTERNAL, false)) continue; QString aPageName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)); QString aTooltip = qs(myWidgetApi->getProperty(FEATURE_TOOLTIP)); QString aCaseId = qs(myWidgetApi->getProperty(_ID)); diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index c4dc84c15..73113c006 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -1630,23 +1630,24 @@ void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const } else if (aObject->document() == aMgr->activeDocument()) { if (hasParameter || hasFeature) { - // disable Edit menu for groups under ImportResult feature bool isEnabled = true; - if (aFeature.get() && aFeature->getKind() == "Group") - { - std::shared_ptr anOwner = - ModelAPI_Tools::compositeOwner (aFeature); - - if (anOwner.get() && anOwner->getKind() == "ImportResult") - { - myMenuMgr->action("EDIT_CMD")->setEnabled(false); - isEnabled = false; + if (aFeature.get()) { + // disable Edit menu for not editable features + isEnabled = aFeature->isEditable(); + + // disable Edit menu for groups under ImportResult feature + if (aFeature->getKind() == "Group") { + std::shared_ptr anOwner = + ModelAPI_Tools::compositeOwner (aFeature); + if (anOwner.get() && anOwner->getKind() == "ImportResult") { + isEnabled = false; + } } } - if (isEnabled) - { - myMenuMgr->action("EDIT_CMD")->setEnabled(true); + myMenuMgr->action("EDIT_CMD")->setEnabled(isEnabled); + + if (isEnabled) { theMenu->addAction(myMenuMgr->action("EDIT_CMD")); if (aCurrentOp && aFeature.get()) { if (aCurrentOp->id().toStdString() == aFeature->getKind()) diff --git a/src/PythonAPI/model/exchange/__init__.py b/src/PythonAPI/model/exchange/__init__.py index 2e43b1241..188d4abf9 100644 --- a/src/PythonAPI/model/exchange/__init__.py +++ b/src/PythonAPI/model/exchange/__init__.py @@ -19,7 +19,8 @@ """Package for Exchange plugin for the Parametric Geometry API of the Modeler. """ -from ExchangeAPI import addImport, addImportSTEP, exportToFile, exportToXAO, exportToSTL +from ExchangeAPI import addImport, addImportXAOMem, addImportSTEP +from ExchangeAPI import exportToFile, exportToXAO, exportToXAOMem, exportToSTL from ExchangeAPI import exportPart, importPart, addImportImage from .tools import * diff --git a/src/XAO/XAO_XaoExporter.cxx b/src/XAO/XAO_XaoExporter.cxx index 4ba49c5f5..9816b43ae 100644 --- a/src/XAO/XAO_XaoExporter.cxx +++ b/src/XAO/XAO_XaoExporter.cxx @@ -655,7 +655,9 @@ const std::string XaoExporter::saveToXml(Xao* xaoObject) xmlChar *xmlbuff; int buffersize; - xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); // format = 1 for node indentation + //xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); // format = 1 for node indentation + // save with encoding to correspond to "saveToFile" and provide the same file size + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1); // format = 1 for node indentation xmlFreeDoc(doc); xmlCleanupGlobals(); -- 2.39.2