Salome HOME
Fix for the issue #2753 : error when dump/load script
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_BooleanCommon.cpp
index c180f725de75577719c1a32c5668da6c997f76c5..539724c33280e2c9a89f562b9871af59a34c0337 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "FeaturesPlugin_BooleanCommon.h"
 
+#include "FeaturesPlugin_Tools.h"
+
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
@@ -31,6 +33,9 @@
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAPI_Face.h>
 #include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
 
 
 //==================================================================================================
@@ -53,6 +58,7 @@ void FeaturesPlugin_BooleanCommon::execute()
 {
   ListOfShape anObjects, aTools, aPlanes;
   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
+  std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompoundObjects;
 
   bool isSimpleMode = false;
 
@@ -63,8 +69,7 @@ void FeaturesPlugin_BooleanCommon::execute()
   }
 
   // Getting objects.
-  AttributeSelectionListPtr anObjectsSelList =
-    selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
+  AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
   for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
@@ -74,21 +79,27 @@ void FeaturesPlugin_BooleanCommon::execute()
     ResultPtr aContext = anObjectAttr->context();
     ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
     if (!isSimpleMode
-        && aResCompSolidPtr.get()
-        && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
+        && aResCompSolidPtr.get())
+    {
       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
+      GeomAPI_Shape::ShapeType aShapeType = aResCompSolidPtr->shape()->shapeType();
+      std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>& aMap =
+        aShapeType == GeomAPI_Shape::COMPSOLID ? aCompSolidsObjects : aCompoundObjects;
+
       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
-        anIt = aCompSolidsObjects.begin();
-      for (; anIt != aCompSolidsObjects.end(); anIt++) {
+        anIt = aMap.begin();
+      for (; anIt != aMap.end(); anIt++) {
         if (anIt->first->isEqual(aContextShape)) {
-          aCompSolidsObjects[anIt->first].push_back(anObject);
+          aMap[anIt->first].push_back(anObject);
           break;
         }
       }
-      if (anIt == aCompSolidsObjects.end()) {
-        aCompSolidsObjects[aContextShape].push_back(anObject);
+      if (anIt == aMap.end()) {
+        aMap[aContextShape].push_back(anObject);
       }
-    } else {
+
+    }
+    else {
       anObjects.push_back(anObject);
     }
   }
@@ -117,8 +128,9 @@ void FeaturesPlugin_BooleanCommon::execute()
   }
 
   int aResultIndex = 0;
-  GeomAlgoAPI_MakeShapeList aMakeShapeList;
-  GeomAPI_DataMapOfShapeShape aMapOfShapes;
+  std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
+  std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+  ListOfShape aResultShapesList;
 
   if (isSimpleMode)
   {
@@ -147,8 +159,7 @@ void FeaturesPlugin_BooleanCommon::execute()
       }
 
       aShape = aCommonAlgo->shape();
-      aMakeShapeList.appendAlgo(aCommonAlgo);
-      aMapOfShapes.merge(aCommonAlgo->mapOfSubShapes());
+      aMakeShapeList->appendAlgo(aCommonAlgo);
     }
 
     GeomAPI_ShapeIterator aShapeIt(aShape);
@@ -156,9 +167,23 @@ void FeaturesPlugin_BooleanCommon::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
-      loadNamingDS(aResultBody, anObjects.front(), anObjects, aShape, aMakeShapeList, aMapOfShapes);
+      GeomShapePtr aBaseShape = anObjects.front();
+      anObjects.pop_front();
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aBaseShape,
+                                               anObjects,
+                                               aMakeShapeList,
+                                               aShape);
       setResult(aResultBody, aResultIndex);
       aResultIndex++;
+
+      aTools = anObjects;
+      FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+      aRBA.resultBody = aResultBody;
+      aRBA.baseShape = aBaseShape;
+      aRBA.makeShape = aMakeShapeList;
+      aResultBaseAlgoList.push_back(aRBA);
+      aResultShapesList.push_back(aShape);
     }
   } else {
     for (ListOfShape::iterator anObjectsIt = anObjects.begin();
@@ -168,7 +193,7 @@ void FeaturesPlugin_BooleanCommon::execute()
       std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
       ListOfShape aListWithObject;
       aListWithObject.push_back(anObject);
-      GeomAlgoAPI_MakeShapeList aMakeShapeList;
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
       std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
       GeomShapePtr aResShape;
 
@@ -185,7 +210,7 @@ void FeaturesPlugin_BooleanCommon::execute()
         std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
           new GeomAlgoAPI_MakeShapeCustom);
         aMkShCustom->addModified(aPlane, aTool);
-        aMakeShapeList.appendAlgo(aMkShCustom);
+        aMakeShapeList->appendAlgo(aMkShCustom);
         aToolsWithPlanes.push_back(aTool);
       }
 
@@ -211,84 +236,224 @@ void FeaturesPlugin_BooleanCommon::execute()
         return;
       }
 
-      aMakeShapeList.appendAlgo(aBoolAlgo);
+      aMakeShapeList->appendAlgo(aBoolAlgo);
 
       GeomAPI_ShapeIterator aShapeIt(aResShape);
       if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX) {
         std::shared_ptr<ModelAPI_ResultBody> aResultBody =
           document()->createBody(data(), aResultIndex);
 
-        loadNamingDS(aResultBody, anObject, aTools, aResShape,
-                     aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()));
+        FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                                 anObject,
+                                                 aTools,
+                                                 aMakeShapeList,
+                                                 aResShape);
         setResult(aResultBody, aResultIndex);
         aResultIndex++;
+
+        FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+        aRBA.resultBody = aResultBody;
+        aRBA.baseShape = anObject;
+        aRBA.makeShape = aMakeShapeList;
+        aResultBaseAlgoList.push_back(aRBA);
+        aResultShapesList.push_back(aResShape);
       }
     }
-  }
 
-  // remove the rest results if there were produced in the previous pass
-  removeResults(aResultIndex);
-}
+    // Compsolids handling
+    for (std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
+      anIt = aCompSolidsObjects.begin();
+      anIt != aCompSolidsObjects.end();
+      ++anIt)
+    {
+      std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
+      ListOfShape& aUsedInOperationSolids = anIt->second;
+
+      // Collecting solids from compsolids which will not be modified in boolean operation.
+      ListOfShape aNotUsedSolids;
+      for (GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID);
+        anExp.more();
+        anExp.next())
+      {
+        std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
+        ListOfShape::iterator aUsedIt = aUsedInOperationSolids.begin();
+        for (; aUsedIt != aUsedInOperationSolids.end(); aUsedIt++) {
+          if (aSolidInCompSolid->isEqual(*aUsedIt)) {
+            break;
+          }
+        }
+        if (aUsedIt == aUsedInOperationSolids.end()) {
+          aNotUsedSolids.push_back(aSolidInCompSolid);
+        }
+      }
 
-//==================================================================================================
-void FeaturesPlugin_BooleanCommon::loadNamingDS(ResultBodyPtr theResultBody,
-                                                const GeomShapePtr theBaseShape,
-                                                const ListOfShape& theTools,
-                                                const GeomShapePtr theResultShape,
-                                                GeomAlgoAPI_MakeShape& theMakeShape,
-                                                GeomAPI_DataMapOfShapeShape& theMapOfShapes)
-{
-  //load result
-  if (theBaseShape->isEqual(theResultShape)) {
-    theResultBody->store(theResultShape, false);
-  } else {
-    const int aModifyVTag = 1;
-    const int aModifyETag = 2;
-    const int aModifyFTag = 3;
-    const int aDeletedTag = 4;
-    /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
-    const int aSubsolidsTag = 5;
-
-    theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
-
-    const std::string aModVName = "Modified_Vertex";
-    const std::string aModEName = "Modified_Edge";
-    const std::string aModFName = "Modified_Face";
-
-    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX,
-                                               aModifyVTag, aModVName, theMapOfShapes, false,
-                                               false, true);
-    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
-                                               aModifyETag, aModEName, theMapOfShapes, false,
-                                               false, true);
-    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
-                                               aModifyFTag, aModFName, theMapOfShapes, false,
-                                               false, true);
-
-    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
-                                     GeomAPI_Shape::VERTEX, aDeletedTag);
-    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
-                                     GeomAPI_Shape::EDGE, aDeletedTag);
-    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
-                                     GeomAPI_Shape::FACE, aDeletedTag);
-
-    for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++)
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
+      std::shared_ptr<GeomAlgoAPI_Boolean> aCommonAlgo(
+        new GeomAlgoAPI_Boolean(aUsedInOperationSolids,
+          aTools,
+          GeomAlgoAPI_Boolean::BOOL_COMMON));
+
+      // Checking that the algorithm worked properly.
+      if (!aCommonAlgo->isDone()) {
+        static const std::string aFeatureError = "Error: Boolean algorithm failed.";
+        setError(aFeatureError);
+        return;
+      }
+      if (aCommonAlgo->shape()->isNull()) {
+        static const std::string aShapeError = "Error: Resulting shape is Null.";
+        setError(aShapeError);
+        return;
+      }
+      if (!aCommonAlgo->isValid()) {
+        std::string aFeatureError = "Error: Resulting shape is not valid.";
+        setError(aFeatureError);
+        return;
+      }
+
+      aMakeShapeList->appendAlgo(aCommonAlgo);
+      GeomShapePtr aResultShape = aCommonAlgo->shape();
+
+      // Add result to not used solids from compsolid.
+      if (!aNotUsedSolids.empty()) {
+        ListOfShape aShapesToAdd = aNotUsedSolids;
+        aShapesToAdd.push_back(aCommonAlgo->shape());
+        std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
+          new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
+        if (!aFillerAlgo->isDone()) {
+          std::string aFeatureError = "Error: PaveFiller algorithm failed.";
+          setError(aFeatureError);
+          return;
+        }
+
+        aMakeShapeList->appendAlgo(aFillerAlgo);
+        aResultShape = aFillerAlgo->shape();
+      }
+
+      GeomAPI_ShapeIterator aShapeIt(aResultShape);
+      if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX)
+      {
+        std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+          document()->createBody(data(), aResultIndex);
+
+        FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                                 aCompSolid,
+                                                 aTools,
+                                                 aMakeShapeList,
+                                                 aResultShape);
+        setResult(aResultBody, aResultIndex);
+        aResultIndex++;
+
+        FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+        aRBA.resultBody = aResultBody;
+        aRBA.baseShape = aCompSolid;
+        aRBA.makeShape = aMakeShapeList;
+        aResultBaseAlgoList.push_back(aRBA);
+        aResultShapesList.push_back(aResultShape);
+      }
+    }
+
+    // Compounds handling
+    for (std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
+      anIt = aCompoundObjects.begin();
+      anIt != aCompoundObjects.end();
+      ++anIt)
     {
-      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX,
-                                                 aModifyVTag, aModVName, theMapOfShapes, false,
-                                                 false, true);
+      std::shared_ptr<GeomAPI_Shape> aCompound = anIt->first;
+      ListOfShape& aUsedInOperationShapes = anIt->second;
+
+      // Collecting shapes from compound which will not be modified in boolean operation.
+      ListOfShape aNotUsedShapes;
+      for (GeomAPI_ShapeIterator aCompIt(aCompound);
+        aCompIt.more();
+        aCompIt.next())
+      {
+        std::shared_ptr<GeomAPI_Shape> aShapeInCompound = aCompIt.current();
+        ListOfShape::iterator aUsedIt = aUsedInOperationShapes.begin();
+        for (; aUsedIt != aUsedInOperationShapes.end(); aUsedIt++) {
+          if (aShapeInCompound->isEqual(*aUsedIt)) {
+            break;
+          }
+        }
+        if (aUsedIt == aUsedInOperationShapes.end()) {
+          aNotUsedShapes.push_back(aShapeInCompound);
+        }
+      }
 
-      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE,
-                                                 aModifyETag, aModEName, theMapOfShapes, false,
-                                                 false, true);
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
+      std::shared_ptr<GeomAlgoAPI_Boolean> aCommonAlgo(
+        new GeomAlgoAPI_Boolean(aUsedInOperationShapes,
+          aTools,
+          GeomAlgoAPI_Boolean::BOOL_COMMON));
 
-      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE,
-                                                 aModifyFTag, aModFName, theMapOfShapes, false,
-                                                 false, true);
+      // Checking that the algorithm worked properly.
+      if (!aCommonAlgo->isDone()) {
+        static const std::string aFeatureError = "Error: Boolean algorithm failed.";
+        setError(aFeatureError);
+        return;
+      }
+      if (aCommonAlgo->shape()->isNull()) {
+        static const std::string aShapeError = "Error: Resulting shape is Null.";
+        setError(aShapeError);
+        return;
+      }
+      if (!aCommonAlgo->isValid()) {
+        std::string aFeatureError = "Error: Resulting shape is not valid.";
+        setError(aFeatureError);
+        return;
+      }
+
+      aMakeShapeList->appendAlgo(aCommonAlgo);
+      GeomShapePtr aResultShape = aCommonAlgo->shape();
+
+      // Add result to not used shape from compound.
+      if (!aNotUsedShapes.empty()) {
+        ListOfShape aShapesForResult = aNotUsedShapes;
+        if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+          for (GeomAPI_ShapeIterator aResultIt(aResultShape); aResultIt.more(); aResultIt.next()) {
+            aShapesForResult.push_back(aResultIt.current());
+          }
+        }
+        else {
+          aShapesForResult.push_back(aResultShape);
+        }
+
+        if (aShapesForResult.size() == 1) {
+          aResultShape = aShapesForResult.front();
+        }
+        else {
+          aResultShape = GeomAlgoAPI_CompoundBuilder::compound(aShapesForResult);
+        }
+      }
+
+      GeomAPI_ShapeIterator aShapeIt(aResultShape);
+      if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX) {
+        std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+          document()->createBody(data(), aResultIndex);
+
+        FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                                 aCompound,
+                                                 aTools,
+                                                 aMakeShapeList,
+                                                 aResultShape);
+        setResult(aResultBody, aResultIndex);
+        aResultIndex++;
 
-      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, aDeletedTag);
-      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, aDeletedTag);
-      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
+        FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+        aRBA.resultBody = aResultBody;
+        aRBA.baseShape = aCompound;
+        aRBA.makeShape = aMakeShapeList;
+        aResultBaseAlgoList.push_back(aRBA);
+        aResultShapesList.push_back(aResultShape);
+      }
     }
+
   }
+
+  // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+  // result shape has been deleted, but in another it was modified or stayed.
+  GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+  FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound);
+
+  // remove the rest results if there were produced in the previous pass
+  removeResults(aResultIndex);
 }