From 593c34845f7ee41dbcfd66ac8304be6c16c55191 Mon Sep 17 00:00:00 2001 From: Christophe Bourcier Date: Mon, 29 Jan 2018 15:33:07 +0100 Subject: [PATCH] Make exportToXAO work even if a group or a field is not valid. --- src/ExchangePlugin/CMakeLists.txt | 3 +- .../ExchangePlugin_ExportFeature.cpp | 139 ++++++++++-------- .../TestExportToXAOWithGroupNotUpdated.py | 122 +++++++++++++++ 3 files changed, 204 insertions(+), 60 deletions(-) create mode 100644 src/ExchangePlugin/Test/TestExportToXAOWithGroupNotUpdated.py diff --git a/src/ExchangePlugin/CMakeLists.txt b/src/ExchangePlugin/CMakeLists.txt index 6d95ce732..237759c99 100644 --- a/src/ExchangePlugin/CMakeLists.txt +++ b/src/ExchangePlugin/CMakeLists.txt @@ -81,7 +81,8 @@ INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}) ADD_UNIT_TESTS(TestImport.py TestExport.py - Test2290.py) + Test2290.py + TestExportToXAOWithGroupNotUpdated.py) SET(DATA_FILES solid.brep diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp index f4e30155f..02b31988b 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp @@ -258,7 +258,6 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) aXao.getGeometry()->setName(aGeometryName); // groups - int aGroupCount = document()->size(ModelAPI_ResultGroup::group()); for (int aGroupIndex = 0; aGroupIndex < aGroupCount; ++aGroupIndex) { ResultGroupPtr aResultGroup = @@ -279,21 +278,31 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) XAO::Group* aXaoGroup = aXao.addGroup(aGroupDimension, aResultGroup->data()->name()); - for (int aSelectionIndex = 0; aSelectionIndex < aSelectionList->size(); ++aSelectionIndex) { - AttributeSelectionPtr aSelection = aSelectionList->value(aSelectionIndex); + try { + for (int aSelectionIndex = 0; aSelectionIndex < aSelectionList->size(); ++aSelectionIndex) { + AttributeSelectionPtr aSelection = aSelectionList->value(aSelectionIndex); - // complex conversion of reference id to element index - // gives bad id in case the selection is done from python script - // => using GeomAlgoAPI_CompoundBuilder::id instead - // int aReferenceID_old = aSelection->Id(); + // complex conversion of reference id to element index + // gives bad id in case the selection is done from python script + // => using GeomAlgoAPI_CompoundBuilder::id instead + // int aReferenceID_old = aSelection->Id(); - int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value()); + int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value()); - std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID); - int anElementID = - aXao.getGeometry()->getElementIndexByReference(aGroupDimension, aReferenceString); + std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID); + int anElementID = + aXao.getGeometry()->getElementIndexByReference(aGroupDimension, aReferenceString); - aXaoGroup->add(anElementID); + aXaoGroup->add(anElementID); + } + } catch (XAO::XAO_Exception& e) { + std::string msg = "An error occurred while exporting group " + aResultGroup->data()->name(); + msg += ".\n"; + msg += e.what(); + msg += "\n"; + msg += "=> skipping this group from XAO export."; + setError(msg); + aXao.removeGroup(aXaoGroup); } } @@ -322,61 +331,73 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) XAO::Field* aXaoField = aXao.addField(aFieldType, aFieldDimension, aTables->columns(), aResultField->data()->name()); - // set components names - AttributeStringArrayPtr aComponents = aFieldFeature->stringArray("components_names"); - for(int aComp = 0; aComp < aComponents->size(); aComp++) { - std::string aName = aComponents->value(aComp); - aXaoField->setComponentName(aComp, aName); - } - AttributeIntArrayPtr aStamps = aFieldFeature->intArray("stamps"); - for (int aStepIndex = 0; aStepIndex < aTables->tables(); aStepIndex++) { - XAO::Step* aStep = aXaoField->addNewStep(aStepIndex); - aStep->setStep(aStepIndex); - int aStampIndex = aStamps->value(aStepIndex); - aStep->setStamp(aStampIndex); - int aNumElements = isWholePart ? aXaoField->countElements() : aTables->rows(); - int aNumComps = aTables->columns(); - std::set aFilledIDs; // to fill the rest by defaults - // omit default values first row - for(int aRow = isWholePart ? 0 : 1; aRow < aNumElements; aRow++) { - for(int aCol = 0; aCol < aNumComps; aCol++) { - int anElementID = 0; - if (!isWholePart) { - // element index actually is the ID of the selection - AttributeSelectionPtr aSelection = aSelectionList->value(aRow - 1); - - // complex conversion of reference id to element index - // gives bad id in case the selection is done from python script - // => using GeomAlgoAPI_CompoundBuilder::id instead - //int aReferenceID_old = aSelection->Id(); - - int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value()); - - std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID); - anElementID = - aXao.getGeometry()->getElementIndexByReference(aFieldDimension, aReferenceString); - } - ModelAPI_AttributeTables::Value aVal = aTables->value( - isWholePart ? 0 : aRow, aCol, aStepIndex); - std::string aStrVal = valToString(aVal, aTables->type()); - aStep->setStringValue(isWholePart ? aRow : anElementID, aCol, aStrVal); - aFilledIDs.insert(anElementID); - } + try { + // set components names + AttributeStringArrayPtr aComponents = aFieldFeature->stringArray("components_names"); + for(int aComp = 0; aComp < aComponents->size(); aComp++) { + std::string aName = aComponents->value(aComp); + aXaoField->setComponentName(aComp, aName); } - if (!isWholePart) { // fill the rest values by default ones - XAO::GeometricElementList::iterator allElem = aXao.getGeometry()->begin(aFieldDimension); - for(; allElem != aXao.getGeometry()->end(aFieldDimension); allElem++) { - if (aFilledIDs.find(allElem->first) != aFilledIDs.end()) - continue; + + AttributeIntArrayPtr aStamps = aFieldFeature->intArray("stamps"); + for (int aStepIndex = 0; aStepIndex < aTables->tables(); aStepIndex++) { + XAO::Step* aStep = aXaoField->addNewStep(aStepIndex); + aStep->setStep(aStepIndex); + int aStampIndex = aStamps->value(aStepIndex); + aStep->setStamp(aStampIndex); + int aNumElements = isWholePart ? aXaoField->countElements() : aTables->rows(); + int aNumComps = aTables->columns(); + std::set aFilledIDs; // to fill the rest by defaults + // omit default values first row + for(int aRow = isWholePart ? 0 : 1; aRow < aNumElements; aRow++) { for(int aCol = 0; aCol < aNumComps; aCol++) { - ModelAPI_AttributeTables::Value aVal = aTables->value(0, aCol, aStepIndex); // default + int anElementID = 0; + if (!isWholePart) { + // element index actually is the ID of the selection + AttributeSelectionPtr aSelection = aSelectionList->value(aRow - 1); + + // complex conversion of reference id to element index + // gives bad id in case the selection is done from python script + // => using GeomAlgoAPI_CompoundBuilder::id instead + //int aReferenceID_old = aSelection->Id(); + + int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value()); + + std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID); + anElementID = + aXao.getGeometry()->getElementIndexByReference(aFieldDimension, aReferenceString); + } + + ModelAPI_AttributeTables::Value aVal = aTables->value( + isWholePart ? 0 : aRow, aCol, aStepIndex); std::string aStrVal = valToString(aVal, aTables->type()); - aStep->setStringValue(allElem->first, aCol, aStrVal); + aStep->setStringValue(isWholePart ? aRow : anElementID, aCol, aStrVal); + aFilledIDs.insert(anElementID); + } + } + if (!isWholePart) { // fill the rest values by default ones + XAO::GeometricElementList::iterator allElem = aXao.getGeometry()->begin(aFieldDimension); + for(; allElem != aXao.getGeometry()->end(aFieldDimension); allElem++) { + if (aFilledIDs.find(allElem->first) != aFilledIDs.end()) + continue; + for(int aCol = 0; aCol < aNumComps; aCol++) { + ModelAPI_AttributeTables::Value aVal = aTables->value(0, aCol, aStepIndex); // default + std::string aStrVal = valToString(aVal, aTables->type()); + aStep->setStringValue(allElem->first, aCol, aStrVal); + } } } } + } catch (XAO::XAO_Exception& e) { + std::string msg = "An error occurred while exporting field " + aResultField->data()->name(); + msg += ".\n"; + msg += e.what(); + msg += "\n"; + msg += "=> skipping this field from XAO export."; + setError(msg); + aXao.removeField(aXaoField); } } diff --git a/src/ExchangePlugin/Test/TestExportToXAOWithGroupNotUpdated.py b/src/ExchangePlugin/Test/TestExportToXAOWithGroupNotUpdated.py new file mode 100644 index 000000000..40e9e8088 --- /dev/null +++ b/src/ExchangePlugin/Test/TestExportToXAOWithGroupNotUpdated.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +# This test checks that exportToXAO works even if a group or a field is not valid + +from salome.shaper import model +from ModelAPI import featureToCompositeFeature +from GeomAPI import GeomAPI_Shape +import tempfile +import os + +def getTmpFileName(ext): + tempdir = tempfile.gettempdir() + tmp_file = tempfile.NamedTemporaryFile(suffix=".%s"%ext, prefix='shaper_', dir=tempdir, delete=False) + tmp_filename = tmp_file.name + return tmp_filename + +tmp_file1 = getTmpFileName("xao") +tmp_file2 = getTmpFileName("xao") + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +# Create a box +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, 0, 0, 50) +SketchLine_2 = Sketch_1.addLine(0, 50, 50, 50) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(50, 50, 50, 0) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(50, 0, 0, 0) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result()) +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_4.result(), 50) +SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_1.result(), 50) +SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_1.result(), SketchLine_3.result()) +SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_2.result(), SketchLine_4.result()) +SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchLine_4.result()) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2r-SketchLine_3r-SketchLine_4r")], model.selection(), 50, 0) +# Create a group with the faces of the box +Group_1_objects = [model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Extrusion_1_1/To_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_3")] +Group_1 = model.addGroup(Part_1_doc, Group_1_objects) +Group_1.setName("Group_faces") +Group_1.result().setName("Group_faces") +# Create a field on the box +Field_1_objects = [model.selection("FACE", "Extrusion_1_1/Generated_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/From_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Extrusion_1_1/To_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_3")] +Field_1 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], Field_1_objects) +Field_1.addStep(0, 0, [[0], [1], [2], [3], [4], [5], [6]]) +# Create a plane to split the box in two parts +Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 25, False) +# Split the Box in two parts +Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("FACE", "Plane_1")]) +# Export the shape with the group and field not updated with the new result +Export_1 = model.exportToXAO(Part_1_doc, tmp_file1) +# Update the group and the field with the last result +Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature()) +Part_1_doc.moveFeature(Field_1.feature(), Group_1.feature()) +# Export the shape with the group and field updated +Export_2 = model.exportToXAO(Part_1_doc, tmp_file2) +model.do() + +# Create a new part +Part_2 = model.addPart(partSet) +Part_2_doc = Part_2.document() +# Import the first XAO file +Import_1 = model.addImport(Part_2_doc, tmp_file1) +model.do() + +# Check results +Import_1_Feature = Import_1.feature() +assert Import_1_Feature.error() == '' +assert Import_1_Feature.name() == "Partition_1_1" +assert len(Import_1_Feature.results()) == 1 +model.testNbSubShapes(Import_1, GeomAPI_Shape.SOLID, [2]) +# No group, no field +aCompositeFeature = featureToCompositeFeature(Import_1_Feature) +assert aCompositeFeature.numberOfSubs(False) == 0 + +# Create a new part +Part_3 = model.addPart(partSet) +Part_3_doc = Part_3.document() + +# Import the second XAO file +Import_2 = model.addImport(Part_3_doc, tmp_file2) +model.do() + +# Check results +Import_2_Feature = Import_2.feature() +assert Import_2_Feature.error() == '' +assert Import_2_Feature.name() == "Partition_1_1" +assert len(Import_2_Feature.results()) == 1 +model.testNbSubShapes(Import_2, GeomAPI_Shape.SOLID, [2]) + +# One group, one field +aCompositeFeature = featureToCompositeFeature(Import_2_Feature) +assert aCompositeFeature.numberOfSubs(False) == 2 + +aFeature1 = aCompositeFeature.subFeature(0, False) +assert aFeature1.getKind() == "Group" +assert aFeature1.name() == "Group_faces" + +aSelectionList = aFeature1.selectionList("group_list") +assert aSelectionList.selectionType() == "face" +assert aSelectionList.size() == 10 + +aFeature2 = aCompositeFeature.subFeature(1, False) +assert aFeature2.getKind() == "Field" +assert aFeature2.name() == "Field_1" +assert aFeature2.intArray("stamps").size() == 1 +assert aFeature2.tables("values").rows() == 7 +assert aFeature2.tables("values").columns() == 1 +assert aFeature2.tables("values").tables() == 1 +assert aFeature2.tables("values").type() == 2 # double +assert aFeature2.selectionList("selected").size() == 6 +model.do() +model.end() + +os.remove(tmp_file1) +os.remove(tmp_file2) -- 2.39.2