Salome HOME
Make exportToXAO work even if a group or a field is not valid.
authorChristophe Bourcier <christophe.bourcier@cea.fr>
Mon, 29 Jan 2018 14:33:07 +0000 (15:33 +0100)
committerChristophe Bourcier <christophe.bourcier@cea.fr>
Mon, 29 Jan 2018 14:33:07 +0000 (15:33 +0100)
src/ExchangePlugin/CMakeLists.txt
src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp
src/ExchangePlugin/Test/TestExportToXAOWithGroupNotUpdated.py [new file with mode: 0644]

index 6d95ce732e0c8ef6c937f3842b08e8f2515fa744..237759c998cde841699a1761f6e12a2048329880 100644 (file)
@@ -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
index f4e30155fba5e4a1ac1fb363f58e64faa092b37e..02b31988bc8193e0de6245ee6ef8bbbb1cc6519b 100644 (file)
@@ -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<int> 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<int> 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 (file)
index 0000000..40e9e80
--- /dev/null
@@ -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)