]> SALOME platform Git repositories - modules/shaper.git/blobdiff - src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
Salome HOME
Task 3.2. Concealment into multi-level Compounds
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Boolean.cpp
index 7f9ce37ac77b4a27d79d5d42dd71133c9edc666f..ec55ff5e303f685cdc742988a7a24c24fe851afc 100644 (file)
@@ -35,6 +35,7 @@
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Partition.h>
 #include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_Tools.h>
 #include <GeomAPI_Face.h>
@@ -153,7 +154,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);
@@ -208,22 +210,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;
@@ -244,7 +255,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;
@@ -305,24 +317,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;
@@ -342,7 +362,8 @@ 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;
@@ -386,18 +407,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;
@@ -409,6 +438,46 @@ 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;
+}
+
+//=================================================================================================
+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)
@@ -420,7 +489,16 @@ void FeaturesPlugin_Boolean::ObjectHierarchy::AddParent(const GeomShapePtr& theS
                                                         const GeomShapePtr& theParent)
 {
   myParent[theShape] = theParent;
-  mySubshapes[theParent].push_back(theShape);
+
+  MapShapeToIndex::iterator aFound = myParentIndices.find(theParent);
+  size_t anIndex = myParentIndices.size();
+  if (aFound == myParentIndices.end()) {
+    myParentIndices[theParent] = anIndex;
+    mySubshapes.push_back(ShapeAndSubshapes(theParent, ListOfShape()));
+  } else
+    anIndex = aFound->second;
+
+  mySubshapes[anIndex].second.push_back(theShape);
 }
 
 GeomShapePtr FeaturesPlugin_Boolean::ObjectHierarchy::Parent(const GeomShapePtr& theShape,
@@ -433,7 +511,7 @@ GeomShapePtr FeaturesPlugin_Boolean::ObjectHierarchy::Parent(const GeomShapePtr&
     if (theMarkProcessed) {
       // mark the parent and all its subs as processed by Boolean algorithm
       myProcessedObjects.insert(aParent);
-      const ListOfShape& aSubs = mySubshapes[aParent];
+      const ListOfShape& aSubs = mySubshapes[myParentIndices[aParent]].second;
       for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
         myProcessedObjects.insert(*anIt);
     }
@@ -473,12 +551,15 @@ void FeaturesPlugin_Boolean::ObjectHierarchy::SplitCompound(const GeomShapePtr&
   theUsed.clear();
   theNotUsed.clear();
 
-  const ListOfShape& aSubs = mySubshapes.find(theCompShape)->second;
+  MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
+  if (aFoundIndex == myParentIndices.end())
+    return; // no such shape
+
+  const ListOfShape& aSubs = mySubshapes[aFoundIndex->second].second;
   SetOfShape aSubsSet;
   aSubsSet.insert(aSubs.begin(), aSubs.end());
 
-  for (GeomAPI_ShapeExplorer anExp(theCompShape, GeomAPI_Shape::SOLID);
-       anExp.more(); anExp.next()) {
+  for (GeomAPI_ShapeIterator anExp(theCompShape); anExp.more(); anExp.next()) {
     GeomShapePtr aCurrent = anExp.current();
     if (aSubsSet.find(aCurrent) == aSubsSet.end())
       theNotUsed.push_back(aCurrent);
@@ -492,6 +573,64 @@ bool FeaturesPlugin_Boolean::ObjectHierarchy::IsEmpty() const
   return myObjects.empty();
 }
 
+void FeaturesPlugin_Boolean::ObjectHierarchy::CompoundsOfUnusedObjects(
+    ListOfShape& theDestination) const
+{
+  SetOfShape aUsedObjects;
+  aUsedObjects.insert(myObjects.begin(), myObjects.end());
+
+  for (std::vector<ShapeAndSubshapes>::const_iterator anIt = mySubshapes.begin();
+       anIt != mySubshapes.end(); ++anIt) {
+    MapShapeToParent::const_iterator aParent = myParent.find(anIt->first);
+    if ((aParent == myParent.end() || !aParent->second) &&
+         anIt->first->shapeType() ==  GeomAPI_Shape::COMPOUND) {
+      // this is a top-level compound
+      GeomShapePtr aCompound = collectUnusedSubs(anIt->first, aUsedObjects);
+      // add to destination non-empty compounds only
+      if (aCompound)
+        theDestination.push_back(aCompound);
+    }
+  }
+}
+
+GeomShapePtr FeaturesPlugin_Boolean::ObjectHierarchy::collectUnusedSubs(
+    GeomShapePtr theTopLevelCompound,
+    const SetOfShape& theUsed) const
+{
+  GeomShapePtr aResult = theTopLevelCompound->emptyCopied();
+  bool isResultEmpty = true;
+
+  for (GeomAPI_ShapeIterator aSub(theTopLevelCompound); aSub.more(); aSub.next()) {
+    GeomShapePtr aCurrent = aSub.current();
+    if (theUsed.find(aCurrent) != theUsed.end())
+      continue; // already used
+
+    MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(aCurrent);
+    if (aCurrent->shapeType() > GeomAPI_Shape::COMPOUND ||
+        aFoundIndex == myParentIndices.end()) {
+      bool isAddShape = true;
+      // check compsolid is fully unused in the Boolean operation
+      if (aCurrent->shapeType() == GeomAPI_Shape::COMPSOLID) {
+        for (GeomAPI_ShapeIterator anIt(aCurrent); isAddShape && anIt.more(); anIt.next())
+          isAddShape = theUsed.find(anIt.current()) == theUsed.end();
+      }
+
+      if (isAddShape) { // low-level shape, add it
+        GeomAlgoAPI_ShapeBuilder::add(aResult, aCurrent);
+        isResultEmpty = false;
+      }
+    } else {
+      GeomShapePtr aCompound = collectUnusedSubs(aCurrent, theUsed);
+      if (aCompound) {
+        GeomAlgoAPI_ShapeBuilder::add(theTopLevelCompound, aCompound);
+        isResultEmpty = false;
+      }
+    }
+  }
+  return isResultEmpty ? GeomShapePtr() : aResult;
+}
+
+
 FeaturesPlugin_Boolean::ObjectHierarchy::Iterator FeaturesPlugin_Boolean::ObjectHierarchy::Begin()
 {
   return Iterator(this);