Salome HOME
Some fixes.
authordbv <dbv@opencascade.com>
Wed, 3 Oct 2018 17:07:47 +0000 (20:07 +0300)
committerdbv <dbv@opencascade.com>
Wed, 3 Oct 2018 17:09:48 +0000 (20:09 +0300)
src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp

index c180f725de75577719c1a32c5668da6c997f76c5..c8cee631839272fbef71d96a584e6e4fad907cae 100644 (file)
@@ -31,6 +31,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 +56,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 +67,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();
@@ -73,22 +76,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) {
+    if (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);
     }
   }
@@ -224,6 +232,187 @@ void FeaturesPlugin_BooleanCommon::execute()
         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);
+        }
+      }
+
+      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);
+      GeomAPI_DataMapOfShapeShape aMapOfShapes;
+      aMapOfShapes.merge(aCommonAlgo->mapOfSubShapes());
+      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);
+        aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
+        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);
+
+        loadNamingDS(aResultBody,
+          aCompSolid,
+          aTools,
+          aResultShape,
+          *aMakeShapeList,
+          aMapOfShapes);
+        setResult(aResultBody, aResultIndex);
+        aResultIndex++;
+      }
+    }
+
+    // Compounds handling
+    for (std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
+      anIt = aCompoundObjects.begin();
+      anIt != aCompoundObjects.end();
+      ++anIt)
+    {
+      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);
+        }
+      }
+
+      std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
+      std::shared_ptr<GeomAlgoAPI_Boolean> aCommonAlgo(
+        new GeomAlgoAPI_Boolean(aUsedInOperationShapes,
+          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);
+      GeomAPI_DataMapOfShapeShape aMapOfShapes;
+      aMapOfShapes.merge(aCommonAlgo->mapOfSubShapes());
+      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);
+
+        loadNamingDS(aResultBody,
+          aCompound,
+          aTools,
+          aResultShape,
+          *aMakeShapeList,
+          aMapOfShapes);
+        setResult(aResultBody, aResultIndex);
+        aResultIndex++;
+      }
+    }
+
   }
 
   // remove the rest results if there were produced in the previous pass
index 9cdf2b7ccd45eafe2de8dcb2a7a4975c838dc6a1..6f0d65f4d923f4824950dd9986ed2e64ab49b191 100644 (file)
@@ -24,6 +24,7 @@
 #include <ModelAPI_Tools.h>
 
 #include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_PaveFiller.h>
 #include <GeomAlgoAPI_ShapeTools.h>
@@ -69,6 +70,8 @@ void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean()
 
   // Store result.
   int aResultIndex = 0;
+  std::vector<ResultBaseAlgo> aResultBaseAlgoList;
+  ListOfShape aResultShapesList;
   ListOfShape::const_iterator aBoolObjIt = aBooleanObjects.cbegin();
   ListOfMakeShape::const_iterator aBoolMSIt = aBooleanMakeShapes.cbegin();
   for(; aBoolObjIt != aBooleanObjects.cend() && aBoolMSIt != aBooleanMakeShapes.cend();
@@ -97,11 +100,24 @@ void FeaturesPlugin_CompositeBoolean::executeCompositeBoolean()
 
       int aModTag = aTag;
       storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt, aModTag);
+
+      ResultBaseAlgo aRBA;
+      aRBA.resultBody = aResultBody;
+      aRBA.baseShape = *aBoolObjIt;
+      aRBA.makeShape = *aBoolMSIt;
+      aRBA.delTag = aModTag;
+      aResultBaseAlgoList.push_back(aRBA);
+      aResultShapesList.push_back((*aBoolMSIt)->shape());
     }
 
     myFeature->setResult(aResultBody, aResultIndex++);
   }
 
+  // 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);
+  storeDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound);
+
   myFeature->removeResults(aResultIndex);
 }
 
@@ -396,6 +412,33 @@ void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr the
     theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt,
       (*anIt)->shapeType() == GeomAPI_Shape::EDGE ?
       GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE, aTag, aName, *aMap.get(), false, false, true);
-    theResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::FACE, aDelTag);
+  }
+}
+
+//==================================================================================================
+void FeaturesPlugin_CompositeBoolean::storeDeletedShapes(
+  std::vector<ResultBaseAlgo>& theResultBaseAlgoList,
+  const ListOfShape& theTools,
+  const GeomShapePtr theResultShapesCompound)
+{
+  for (std::vector<ResultBaseAlgo>::iterator anIt = theResultBaseAlgoList.begin();
+    anIt != theResultBaseAlgoList.end();
+    ++anIt)
+  {
+    ResultBaseAlgo& aRCA = *anIt;
+    aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(),
+      aRCA.baseShape,
+      GeomAPI_Shape::FACE,
+      aRCA.delTag,
+      theResultShapesCompound);
+
+    for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++)
+    {
+      aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(),
+        *anIter,
+        GeomAPI_Shape::FACE,
+        aRCA.delTag,
+        theResultShapesCompound);
+    }
   }
 }
index 1e6a28175fff134bfeb721c6c1761c1d7306aadf..3f07d107b14ffc804f1e11285deed8b5ac447e3c 100644 (file)
@@ -50,6 +50,14 @@ public:
   /// Creates a new part document if needed.
   FEATURESPLUGIN_EXPORT virtual void executeCompositeBoolean();
 
+protected:
+  struct ResultBaseAlgo {
+    ResultBodyPtr resultBody;
+    GeomShapePtr baseShape;
+    std::shared_ptr<GeomAlgoAPI_MakeShape> makeShape;
+    int delTag;
+  };
+
 protected:
   FeaturesPlugin_CompositeBoolean(){};
 
@@ -82,6 +90,11 @@ protected:
                                 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
                                 int& theTag);
 
+  /// Stores deleted shapes.
+  void storeDeletedShapes(std::vector<ResultBaseAlgo>& theResultBaseAlgoList,
+                          const ListOfShape& theTools,
+                          const GeomShapePtr theResultShapesCompound);
+
 protected:
   ModelAPI_Feature* myFeature;
   OperationType myOperationType;
index 1b8c4d13e871d61edfa328944ca53298e0c9d75c..d46d2931622106b6f6366580cd1e943c95893d2f 100644 (file)
@@ -1688,8 +1688,10 @@ bool FeaturesPlugin_ValidatorBooleanCommonSelection::isValid(
     }
     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
     GeomShapePtr aContextShape;
-    if (!aShape.get() && aContext.get()) {
+    if (aContext.get()) {
       aContextShape = aContext->shape();
+    }
+    if (!aShape.get()) {
       aShape = aContextShape;
     }
     if (!aShape.get()) {