Salome HOME
Small refactoring: separate storing a compound of sub-results.
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Boolean.cpp
index 856d8d4679fdc586284e21de592f2f006e08e6eb..066bf02af3c038979b3b535fa332e8c266f9da08 100644 (file)
@@ -65,6 +65,21 @@ void FeaturesPlugin_Boolean::initAttributes()
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
 }
 
+//=================================================================================================
+void FeaturesPlugin_Boolean::initVersion(const int theVersion)
+{
+  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(theVersion);
+  }
+}
+
 //=================================================================================================
 FeaturesPlugin_Boolean::OperationType FeaturesPlugin_Boolean::operationType()
 {
@@ -154,7 +169,8 @@ bool FeaturesPlugin_Boolean::processObject(
     const ListOfShape& thePlanes,
     int& theResultIndex,
     std::vector<FeaturesPlugin_Tools::ResultBaseAlgo>& theResultBaseAlgoList,
-    ListOfShape& theResultShapesList)
+    ListOfShape& theResultShapesList,
+    GeomShapePtr theResultCompound)
 {
   ListOfShape aListWithObject;
   aListWithObject.push_back(theObject);
@@ -209,22 +225,31 @@ bool FeaturesPlugin_Boolean::processObject(
 
   GeomAPI_ShapeIterator aShapeIt(aResShape);
   if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX) {
-    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
-        document()->createBody(data(), theResultIndex);
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody;
 
-    // tools should be added to the list to fulfill the correct history of modification
-    aListWithObject.insert(aListWithObject.end(), theTools.begin(), theTools.end());
-
-    ListOfShape aUsedTools = theTools;
-    aUsedTools.insert(aUsedTools.end(), thePlanes.begin(), thePlanes.end());
+    if (theResultCompound) { // store BOP result to the compound
+      std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
+      aBuilder->add(theResultCompound, aResShape);
+      aMakeShapeList->appendAlgo(aBuilder);
+    }
+    else { // create a separate ResultBody
+      aResultBody = document()->createBody(data(), theResultIndex);
+
+      // tools should be added to the list to fulfill the correct history of modification
+      aListWithObject.insert(aListWithObject.end(), theTools.begin(), theTools.end());
+
+      ListOfShape aUsedTools = theTools;
+      aUsedTools.insert(aUsedTools.end(), thePlanes.begin(), thePlanes.end());
+
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aListWithObject,
+                                               aUsedTools,
+                                               aMakeShapeList,
+                                               aResShape);
+      setResult(aResultBody, theResultIndex);
+      ++theResultIndex;
+    }
 
-    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                             aListWithObject,
-                                             aUsedTools,
-                                             aMakeShapeList,
-                                             aResShape);
-    setResult(aResultBody, theResultIndex);
-    ++theResultIndex;
 
     FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
     aRBA.resultBody = aResultBody;
@@ -245,7 +270,8 @@ bool FeaturesPlugin_Boolean::processCompsolid(
     const ListOfShape& thePlanes,
     int& theResultIndex,
     std::vector<FeaturesPlugin_Tools::ResultBaseAlgo>& theResultBaseAlgoList,
-    ListOfShape& theResultShapesList)
+    ListOfShape& theResultShapesList,
+    GeomShapePtr theResultCompound)
 {
   ListOfShape aUsedInOperationSolids;
   ListOfShape aNotUsedSolids;
@@ -306,24 +332,32 @@ bool FeaturesPlugin_Boolean::processCompsolid(
   GeomAPI_ShapeIterator aShapeIt(aResultShape);
   if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX)
   {
-    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
-        document()->createBody(data(), theResultIndex);
-
-    ListOfShape aCompSolidList;
-    aCompSolidList.push_back(theCompsolid);
-    // tools should be added to the list to fulfill the correct history of modification
-    aCompSolidList.insert(aCompSolidList.end(), theTools.begin(), theTools.end());
-
-    ListOfShape aUsedTools = theTools;
-    aUsedTools.insert(aUsedTools.end(), thePlanes.begin(), thePlanes.end());
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody;
 
-    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                             aCompSolidList,
-                                             aUsedTools,
-                                             aMakeShapeList,
-                                             aResultShape);
-    setResult(aResultBody, theResultIndex);
-    ++theResultIndex;
+    if (theResultCompound) { // store BOP result to the compound
+      std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
+      aBuilder->add(theResultCompound, aResultShape);
+      aMakeShapeList->appendAlgo(aBuilder);
+    }
+    else { // create a separate ResultBody
+      aResultBody = document()->createBody(data(), theResultIndex);
+
+      ListOfShape aCompSolidList;
+      aCompSolidList.push_back(theCompsolid);
+      // tools should be added to the list to fulfill the correct history of modification
+      aCompSolidList.insert(aCompSolidList.end(), theTools.begin(), theTools.end());
+
+      ListOfShape aUsedTools = theTools;
+      aUsedTools.insert(aUsedTools.end(), thePlanes.begin(), thePlanes.end());
+
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aCompSolidList,
+                                               aUsedTools,
+                                               aMakeShapeList,
+                                               aResultShape);
+      setResult(aResultBody, theResultIndex);
+      ++theResultIndex;
+    }
 
     FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
     aRBA.resultBody = aResultBody;
@@ -343,11 +377,17 @@ bool FeaturesPlugin_Boolean::processCompound(
     const ListOfShape& theTools,
     int& theResultIndex,
     std::vector<FeaturesPlugin_Tools::ResultBaseAlgo>& theResultBaseAlgoList,
-    ListOfShape& theResultShapesList)
+    ListOfShape& theResultShapesList,
+    GeomShapePtr theResultCompound)
 {
   ListOfShape aUsedInOperationShapes;
   ListOfShape aNotUsedShapes;
   theCompoundHierarchy.SplitCompound(theCompound, aUsedInOperationShapes, aNotUsedShapes);
+  if (theResultCompound) {
+    // Not necessary to keep all subs of the current compound,
+    // all unused solids are already stored in the result compound.
+    aNotUsedShapes.clear();
+  }
 
   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
   std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(
@@ -387,18 +427,26 @@ bool FeaturesPlugin_Boolean::processCompound(
 
   GeomAPI_ShapeIterator aShapeIt(aResultShape);
   if (aShapeIt.more() || aResultShape->shapeType() == GeomAPI_Shape::VERTEX) {
-    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
-        document()->createBody(data(), theResultIndex);
-
-    ListOfShape aCompoundList;
-    aCompoundList.push_back(theCompound);
-    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
-                                             aCompoundList,
-                                             theTools,
-                                             aMakeShapeList,
-                                             aResultShape);
-    setResult(aResultBody, theResultIndex);
-    ++theResultIndex;
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody;
+
+    if (theResultCompound) { // store BOP result to the compound
+      std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
+      aBuilder->add(theResultCompound, aResultShape);
+      aMakeShapeList->appendAlgo(aBuilder);
+    }
+    else { // create a separate ResultBody
+      aResultBody = document()->createBody(data(), theResultIndex);
+
+      ListOfShape aCompoundList;
+      aCompoundList.push_back(theCompound);
+      FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                               aCompoundList,
+                                               theTools,
+                                               aMakeShapeList,
+                                               aResultShape);
+      setResult(aResultBody, theResultIndex);
+      ++theResultIndex;
+    }
 
     FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
     aRBA.resultBody = aResultBody;
@@ -410,6 +458,82 @@ bool FeaturesPlugin_Boolean::processCompound(
   return true;
 }
 
+//==================================================================================================
+GeomShapePtr FeaturesPlugin_Boolean::keepUnusedSubsOfCompound(
+    const GeomShapePtr& theResult,
+    const ObjectHierarchy& theObjectsHierarchy,
+    const ObjectHierarchy& theToolsHierarchy,
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList> theMakeShapeList)
+{
+  ListOfShape aCompounds;
+  theObjectsHierarchy.CompoundsOfUnusedObjects(aCompounds);
+  theToolsHierarchy.CompoundsOfUnusedObjects(aCompounds);
+
+  GeomShapePtr aResultShape = theResult;
+  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());
+    }
+
+    if (theResult)
+      aBuilder->add(aResultShape, theResult);
+
+    theMakeShapeList->appendAlgo(aBuilder);
+  }
+  return aResultShape;
+}
+
+//=================================================================================================
+void FeaturesPlugin_Boolean::storeResult(
+    const ListOfShape& theObjects,
+    const ListOfShape& theTools,
+    const GeomShapePtr theResultShape,
+    int& theResultIndex,
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList> theMakeShapeList,
+    std::vector<FeaturesPlugin_Tools::ResultBaseAlgo>& theResultBaseAlgoList)
+{
+  if (!theResultShape)
+    return;
+
+  std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+      document()->createBody(data(), theResultIndex);
+
+  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
+                                           theObjects,
+                                           theTools,
+                                           theMakeShapeList,
+                                           theResultShape);
+  setResult(aResultBody, theResultIndex++);
+
+  // merge algorithms
+  FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+  aRBA.resultBody = aResultBody;
+  aRBA.baseShape = theObjects.front();
+  for (std::vector<FeaturesPlugin_Tools::ResultBaseAlgo>::iterator
+       aRBAIt = theResultBaseAlgoList.begin();
+       aRBAIt != theResultBaseAlgoList.end(); ++aRBAIt) {
+    theMakeShapeList->appendAlgo(aRBAIt->makeShape);
+  }
+  aRBA.makeShape = theMakeShapeList;
+  theResultBaseAlgoList.clear();
+  theResultBaseAlgoList.push_back(aRBA);
+}
+
+//=================================================================================================
+int FeaturesPlugin_Boolean::version()
+{
+  AttributeIntegerPtr aVersionAttr = integer(VERSION_ID());
+  int aVersion = 0;
+  if (aVersionAttr && aVersionAttr->isInitialized())
+    aVersion = aVersionAttr->value();
+  return aVersion;
+}
+
 //=================================================================================================
 
 void FeaturesPlugin_Boolean::ObjectHierarchy::AddObject(const GeomShapePtr& theObject)
@@ -487,16 +611,14 @@ void FeaturesPlugin_Boolean::ObjectHierarchy::SplitCompound(const GeomShapePtr&
   if (aFoundIndex == myParentIndices.end())
     return; // no such shape
 
-  const ListOfShape& aSubs = mySubshapes[aFoundIndex->second].second;
+  theUsed = mySubshapes[aFoundIndex->second].second;
   SetOfShape aSubsSet;
-  aSubsSet.insert(aSubs.begin(), aSubs.end());
+  aSubsSet.insert(theUsed.begin(), theUsed.end());
 
   for (GeomAPI_ShapeIterator anExp(theCompShape); anExp.more(); anExp.next()) {
     GeomShapePtr aCurrent = anExp.current();
     if (aSubsSet.find(aCurrent) == aSubsSet.end())
       theNotUsed.push_back(aCurrent);
-    else
-      theUsed.push_back(aCurrent);
   }
 }