Salome HOME
Task 3.2. Concealment into multi-level Compounds
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_BooleanFuse.cpp
index 497d529e43ad221c3941eac83a2529ac3fce4750..65e5c0f4cb6e7a95578489b57de9c6cb48a30d9f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Session.h>
 #include <GeomAlgoAPI_Boolean.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_Tools.h>
 #include <GeomAlgoAPI_UnifySameDomain.h>
+
 #include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+static const int THE_FUSE_VERSION_1 = 20190506;
 
 //==================================================================================================
 FeaturesPlugin_BooleanFuse::FeaturesPlugin_BooleanFuse()
@@ -55,6 +61,17 @@ void FeaturesPlugin_BooleanFuse::initAttributes()
 
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
+
+  AttributePtr aVerAttr = data()->addAttribute(VERSION_ID(), ModelAPI_AttributeInteger::typeId());
+  aVerAttr->setIsArgument(false);
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERSION_ID());
+  if (!integer(VERSION_ID())->isInitialized() &&
+      !selectionList(OBJECT_LIST_ID())->isInitialized() &&
+      !selectionList(TOOL_LIST_ID())->isInitialized()) {
+    // this is a newly created feature (not read from file),
+    // so, initialize the latest version
+    integer(VERSION_ID())->setValue(THE_FUSE_VERSION_1);
+  }
 }
 
 //==================================================================================================
@@ -95,6 +112,14 @@ void FeaturesPlugin_BooleanFuse::execute()
     return;
   }
 
+  // version of FUSE feature
+  AttributeIntegerPtr aVersionAttr = integer(VERSION_ID());
+  int aFuseVersion = 0;
+  if (aVersionAttr && aVersionAttr->isInitialized())
+    aFuseVersion = aVersionAttr->value();
+
+////  isSimpleCreation = isSimpleCreation && aFuseVersion < THE_FUSE_VERSION_1;
+
   // Collecting all solids which will be fused.
   ListOfShape aSolidsToFuse;
   aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
@@ -221,6 +246,12 @@ void FeaturesPlugin_BooleanFuse::execute()
     aMakeShapeList->appendAlgo(aUnifyAlgo);
   }
 
+  if (aFuseVersion == THE_FUSE_VERSION_1) {
+    // merge hierarchies of compounds containing objects and tools
+    // and append the result of the FUSE operation
+    aShape = keepUnusedSubsOfCompound(aShape, anObjectsHierarchy, aToolsHierarchy, aMakeShapeList);
+  }
+
   int aResultIndex = 0;
 
   ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
@@ -243,3 +274,32 @@ void FeaturesPlugin_BooleanFuse::execute()
   // remove the rest results if there were produced in the previous pass
   removeResults(aResultIndex);
 }
+
+//==================================================================================================
+GeomShapePtr FeaturesPlugin_BooleanFuse::keepUnusedSubsOfCompound(
+    const GeomShapePtr& theFuseResult,
+    const ObjectHierarchy& theObjectsHierarchy,
+    const ObjectHierarchy& theToolsHierarchy,
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList> theMakeShapeList)
+{
+  ListOfShape aCompounds;
+  theObjectsHierarchy.CompoundsOfUnusedObjects(aCompounds);
+  theToolsHierarchy.CompoundsOfUnusedObjects(aCompounds);
+
+  GeomShapePtr aResultShape = theFuseResult;
+  if (!aCompounds.empty()) {
+    aResultShape = aCompounds.front();
+    aCompounds.pop_front();
+
+    std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
+    for (ListOfShape::iterator anIt = aCompounds.begin(); anIt != aCompounds.end(); ++anIt) {
+      for (GeomAPI_ShapeIterator aSub(*anIt); aSub.more(); aSub.next())
+        aBuilder->add(aResultShape, aSub.current());
+    }
+
+    aBuilder->add(aResultShape, theFuseResult);
+
+    theMakeShapeList->appendAlgo(aBuilder);
+  }
+  return aResultShape;
+}