]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Extract ShapeHierarchy as a separate object
authorazv <azv@opencascade.com>
Tue, 11 Feb 2020 07:29:43 +0000 (10:29 +0300)
committerazv <azv@opencascade.com>
Wed, 12 Feb 2020 10:06:28 +0000 (13:06 +0300)
15 files changed:
src/FeaturesPlugin/FeaturesPlugin_BooleanCommon.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanFill.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.h
src/FeaturesPlugin/FeaturesPlugin_Union.cpp
src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h
src/GeomAPI/CMakeLists.txt
src/GeomAPI/GeomAPI_ShapeHierarchy.cpp [new file with mode: 0644]
src/GeomAPI/GeomAPI_ShapeHierarchy.h [new file with mode: 0644]
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h

index be2c09a50fd9bd8df72c94df2cf828210382612b..2a7b41efd7e1447364c69e691d2fcf0a22a4986c 100644 (file)
@@ -59,7 +59,7 @@ void FeaturesPlugin_BooleanCommon::initAttributes()
 void FeaturesPlugin_BooleanCommon::execute()
 {
   ListOfShape aPlanes;
-  ObjectHierarchy anObjects, aTools;
+  GeomAPI_ShapeHierarchy anObjects, aTools;
 
   bool isSimpleMode = false;
 
@@ -80,7 +80,7 @@ void FeaturesPlugin_BooleanCommon::execute()
       !processAttribute(TOOL_LIST_ID(), aTools, aPlanes))
     return;
 
-  if (anObjects.IsEmpty() || (!isSimpleMode && aTools.IsEmpty() && aPlanes.empty())) {
+  if (anObjects.empty() || (!isSimpleMode && aTools.empty() && aPlanes.empty())) {
     std::string aFeatureError = "Error: Not enough objects for boolean operation.";
     setError(aFeatureError);
     return;
@@ -98,9 +98,9 @@ void FeaturesPlugin_BooleanCommon::execute()
   ListOfShape aResultShapesList;
 
   if (isSimpleMode) {
-    ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin();
+    GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
     GeomShapePtr aShape = *anObjectsIt;
-    for (++anObjectsIt; anObjectsIt != anObjects.End(); ++anObjectsIt) {
+    for (++anObjectsIt; anObjectsIt != anObjects.end(); ++anObjectsIt) {
       std::shared_ptr<GeomAlgoAPI_Boolean> aCommonAlgo(
         new GeomAlgoAPI_Boolean(aShape,
                                 *anObjectsIt,
@@ -126,7 +126,7 @@ void FeaturesPlugin_BooleanCommon::execute()
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
 
-      ListOfShape anObjectList = anObjects.Objects();
+      ListOfShape anObjectList = anObjects.objects();
       ListOfShape aToolsList;
       FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
                                                anObjectList,
@@ -154,39 +154,39 @@ void FeaturesPlugin_BooleanCommon::execute()
     }
 
     bool isOk = true;
-    for (ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin();
-         anObjectsIt != anObjects.End() && isOk;
+    for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
+         anObjectsIt != anObjects.end() && isOk;
          ++anObjectsIt)
     {
       GeomShapePtr anObject = *anObjectsIt;
-      GeomShapePtr aParent = anObjects.Parent(anObject);
+      GeomShapePtr aParent = anObjects.parent(anObject);
 
       if (aParent) {
         GeomAPI_Shape::ShapeType aShapeType = aParent->shapeType();
         if (aShapeType == GeomAPI_Shape::COMPOUND) {
           // Compound handling
           isOk = processCompound(GeomAlgoAPI_Tools::BOOL_COMMON,
-                                 anObjects, aParent, aTools.Objects(),
+                                 anObjects, aParent, aTools.objects(),
                                  aResultIndex, aResultBaseAlgoList, aResultShapesList,
                                  aResultCompound);
         }
         else if (aShapeType == GeomAPI_Shape::COMPSOLID) {
           // Compsolid handling
           isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_COMMON,
-                                  anObjects, aParent, aTools.Objects(), ListOfShape(),
+                                  anObjects, aParent, aTools.objects(), ListOfShape(),
                                   aResultIndex, aResultBaseAlgoList, aResultShapesList,
                                   aResultCompound);
         }
       } else {
         // process object as is
         isOk = processObject(GeomAlgoAPI_Tools::BOOL_COMMON,
-                             anObject, aTools.Objects(), aPlanes,
+                             anObject, aTools.objects(), aPlanes,
                              aResultIndex, aResultBaseAlgoList, aResultShapesList,
                              aResultCompound);
       }
     }
 
-    storeResult(anObjects.Objects(), aTools.Objects(), aResultCompound, aResultIndex,
+    storeResult(anObjects.objects(), aTools.objects(), aResultCompound, aResultIndex,
                 aMakeShapeList, aResultBaseAlgoList);
   }
 
@@ -195,7 +195,7 @@ void FeaturesPlugin_BooleanCommon::execute()
   if (!aResultCompound)
     aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
   FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
-                                          aTools.Objects(),
+                                          aTools.objects(),
                                           aResultCompound);
 
   // remove the rest results if there were produced in the previous pass
index bc67a28e119c0178cb1e0af003b7392cbb06b8c2..e00e3e9ff251b0f3af56ead3f56e2241346c4fd4 100644 (file)
@@ -51,7 +51,7 @@ void FeaturesPlugin_BooleanCut::initAttributes()
 //==================================================================================================
 void FeaturesPlugin_BooleanCut::execute()
 {
-  ObjectHierarchy anObjects, aTools;
+  GeomAPI_ShapeHierarchy anObjects, aTools;
   ListOfShape aPlanes;
 
   // Getting objects and tools
@@ -61,7 +61,7 @@ void FeaturesPlugin_BooleanCut::execute()
 
   int aResultIndex = 0;
 
-  if(anObjects.IsEmpty() || aTools.IsEmpty()) {
+  if(anObjects.empty() || aTools.empty()) {
     std::string aFeatureError = "Error: Not enough objects for boolean operation.";
     setError(aFeatureError);
     return;
@@ -82,38 +82,38 @@ void FeaturesPlugin_BooleanCut::execute()
 
   // For solids cut each object with all tools.
   bool isOk = true;
-  for (ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin();
-       anObjectsIt != anObjects.End() && isOk;
+  for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
+       anObjectsIt != anObjects.end() && isOk;
        ++anObjectsIt) {
     GeomShapePtr anObject = *anObjectsIt;
-    GeomShapePtr aParent = anObjects.Parent(anObject);
+    GeomShapePtr aParent = anObjects.parent(anObject);
 
     if (aParent) {
       GeomAPI_Shape::ShapeType aShapeType = aParent->shapeType();
       if (aShapeType == GeomAPI_Shape::COMPOUND) {
         // Compound handling
         isOk = processCompound(GeomAlgoAPI_Tools::BOOL_CUT,
-                               anObjects, aParent, aTools.Objects(),
+                               anObjects, aParent, aTools.objects(),
                                aResultIndex, aResultBaseAlgoList, aResultShapesList,
                                aResultCompound);
       }
       else if (aShapeType == GeomAPI_Shape::COMPSOLID) {
         // Compsolid handling
         isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_CUT,
-                                anObjects, aParent, aTools.Objects(), ListOfShape(),
+                                anObjects, aParent, aTools.objects(), ListOfShape(),
                                 aResultIndex, aResultBaseAlgoList, aResultShapesList,
                                 aResultCompound);
       }
     } else {
       // process object as is
       isOk = processObject(GeomAlgoAPI_Tools::BOOL_CUT,
-                           anObject, aTools.Objects(), aPlanes,
+                           anObject, aTools.objects(), aPlanes,
                            aResultIndex, aResultBaseAlgoList, aResultShapesList,
                            aResultCompound);
     }
   }
 
-  storeResult(anObjects.Objects(), aTools.Objects(), aResultCompound, aResultIndex,
+  storeResult(anObjects.objects(), aTools.objects(), aResultCompound, aResultIndex,
               aMakeShapeList, aResultBaseAlgoList);
 
   // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
@@ -121,7 +121,7 @@ void FeaturesPlugin_BooleanCut::execute()
   if (!aResultCompound)
     aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
   FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
-                                          aTools.Objects(),
+                                          aTools.objects(),
                                           aResultCompound);
 
   // remove the rest results if there were produced in the previous pass
index 3f6dd4cc0ff8f48d6db7d51d57a9c8921737966b..cb039b01a6b243854b251749cfb638b5764c7ca6 100644 (file)
@@ -57,7 +57,7 @@ void FeaturesPlugin_BooleanFill::initAttributes()
 void FeaturesPlugin_BooleanFill::execute()
 {
   std::string anError;
-  ObjectHierarchy anObjects, aTools;
+  GeomAPI_ShapeHierarchy anObjects, aTools;
   ListOfShape aPlanes;
 
   // Getting objects.
@@ -72,7 +72,7 @@ void FeaturesPlugin_BooleanFill::execute()
 
   int aResultIndex = 0;
 
-  if (anObjects.IsEmpty() || (aTools.IsEmpty() && aPlanes.empty())) {
+  if (anObjects.empty() || (aTools.empty() && aPlanes.empty())) {
     std::string aFeatureError = "Error: Not enough objects for boolean operation.";
     setError(aFeatureError);
     return;
@@ -92,30 +92,30 @@ void FeaturesPlugin_BooleanFill::execute()
 
   // For solids cut each object with all tools.
   bool isOk = true;
-  for (ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin();
-       anObjectsIt != anObjects.End() && isOk;
+  for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
+       anObjectsIt != anObjects.end() && isOk;
        ++anObjectsIt) {
     GeomShapePtr anObject = *anObjectsIt;
-    GeomShapePtr aParent = anObjects.Parent(anObject, false);
+    GeomShapePtr aParent = anObjects.parent(anObject, false);
 
     if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID) {
       // get parent once again to mark it and the subs as processed
-      aParent = anObjects.Parent(anObject);
+      aParent = anObjects.parent(anObject);
       // compsolid handling
       isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_PARTITION,
-                              anObjects, aParent, aTools.Objects(), aPlanes,
+                              anObjects, aParent, aTools.objects(), aPlanes,
                               aResultIndex, aResultBaseAlgoList, aResultShapesList,
                               aResultCompound);
     } else {
       // process object as is
       isOk = processObject(GeomAlgoAPI_Tools::BOOL_PARTITION,
-                           anObject, aTools.Objects(), aPlanes,
+                           anObject, aTools.objects(), aPlanes,
                            aResultIndex, aResultBaseAlgoList, aResultShapesList,
                            aResultCompound);
     }
   }
 
-  storeResult(anObjects.Objects(), aTools.Objects(), aResultCompound, aResultIndex,
+  storeResult(anObjects.objects(), aTools.objects(), aResultCompound, aResultIndex,
               aMakeShapeList, aResultBaseAlgoList);
 
   // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
@@ -123,7 +123,7 @@ void FeaturesPlugin_BooleanFill::execute()
   if (!aResultCompound)
     aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
   FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
-                                          aTools.Objects(),
+                                          aTools.objects(),
                                           aResultCompound);
 
   // remove the rest results if there were produced in the previous pass
index a7a1b0cc10643c378d7fc512f4ed984a6b6ac3be..77d5bcefd8a04c5d50aa76ab55bcaf930a492a1f 100644 (file)
@@ -67,7 +67,7 @@ void FeaturesPlugin_BooleanFuse::initAttributes()
 void FeaturesPlugin_BooleanFuse::execute()
 {
   std::string anError;
-  ObjectHierarchy anObjectsHierarchy, aToolsHierarchy;
+  GeomAPI_ShapeHierarchy anObjectsHierarchy, aToolsHierarchy;
   ListOfShape aPlanes;
 
   bool isSimpleCreation = false;
@@ -90,9 +90,9 @@ void FeaturesPlugin_BooleanFuse::execute()
 
   ListOfShape anObjects, aTools, anEdgesAndFaces;
   // all objects except edges and faces
-  anObjectsHierarchy.ObjectsByType(anEdgesAndFaces, anObjects,
+  anObjectsHierarchy.objectsByType(anEdgesAndFaces, anObjects,
                                    GeomAPI_Shape::FACE, GeomAPI_Shape::EDGE);
-  aToolsHierarchy.ObjectsByType(anEdgesAndFaces, aTools,
+  aToolsHierarchy.objectsByType(anEdgesAndFaces, aTools,
                                 GeomAPI_Shape::FACE, GeomAPI_Shape::EDGE);
 
   if ((anObjects.size() + aTools.size() + anEdgesAndFaces.size()) < 2) {
@@ -113,18 +113,18 @@ void FeaturesPlugin_BooleanFuse::execute()
   // in boolean operation and will be added to result.
   bool isProcessCompsolid = !isSimpleCreation || !aFuseVersion.empty();
   ListOfShape aShapesToAdd;
-  for (ObjectHierarchy::Iterator anObjectsIt = anObjectsHierarchy.Begin();
-       isProcessCompsolid && anObjectsIt != anObjectsHierarchy.End();
+  for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjectsHierarchy.begin();
+       isProcessCompsolid && anObjectsIt != anObjectsHierarchy.end();
        ++anObjectsIt) {
     GeomShapePtr anObject = *anObjectsIt;
-    GeomShapePtr aParent = anObjectsHierarchy.Parent(anObject, false);
+    GeomShapePtr aParent = anObjectsHierarchy.parent(anObject, false);
 
     if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID) {
       // mark all subs of this parent as precessed to avoid handling twice
-      aParent = anObjectsHierarchy.Parent(anObject);
+      aParent = anObjectsHierarchy.parent(anObject);
 
       ListOfShape aUsed, aNotUsed;
-      anObjectsHierarchy.SplitCompound(aParent, aUsed, aNotUsed);
+      anObjectsHierarchy.splitCompound(aParent, aUsed, aNotUsed);
       aShapesToAdd.insert(aShapesToAdd.end(), aNotUsed.begin(), aNotUsed.end());
     }
   }
index 9d053f0e9d6b51d0d7d03fd71d6641721352da16..0fde78876d208d5e6d67217432c0b056086299be 100644 (file)
@@ -54,7 +54,7 @@ void FeaturesPlugin_BooleanSmash::initAttributes()
 void FeaturesPlugin_BooleanSmash::execute()
 {
   std::string anError;
-  ObjectHierarchy anObjectsHistory, aToolsHistory;
+  GeomAPI_ShapeHierarchy anObjectsHistory, aToolsHistory;
   ListOfShape aPlanes;
 
   // Getting objects and tools.
@@ -64,41 +64,41 @@ void FeaturesPlugin_BooleanSmash::execute()
 
   int aResultIndex = 0;
 
-  if (anObjectsHistory.IsEmpty() || aToolsHistory.IsEmpty()) {
+  if (anObjectsHistory.empty() || aToolsHistory.empty()) {
     std::string aFeatureError = "Error: Not enough objects for boolean operation.";
     setError(aFeatureError);
     return;
   }
 
   // Collecting all shapes which will be smashed.
-  ListOfShape aShapesToSmash = anObjectsHistory.Objects();
+  ListOfShape aShapesToSmash = anObjectsHistory.objects();
 
   // List of original shapes for naming.
   ListOfShape anOriginalShapes;
   anOriginalShapes.insert(anOriginalShapes.end(), aShapesToSmash.begin(), aShapesToSmash.end());
-  ListOfShape aTools = aToolsHistory.Objects();
+  ListOfShape aTools = aToolsHistory.objects();
   anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
 
   // Collecting solids from compsolids which will not be modified in
   // boolean operation and will be added to result.
   ListOfShape aShapesToAdd;
-  for (ObjectHierarchy::Iterator anIt = anObjectsHistory.Begin();
-       anIt != anObjectsHistory.End();
+  for (GeomAPI_ShapeHierarchy::iterator anIt = anObjectsHistory.begin();
+       anIt != anObjectsHistory.end();
        ++anIt)
   {
-    GeomShapePtr aParent = anObjectsHistory.Parent(*anIt, false);
+    GeomShapePtr aParent = anObjectsHistory.parent(*anIt, false);
     if (aParent) {
       anOriginalShapes.push_back(aParent);
 
       ListOfShape aUsed, aNotUsed;
-      anObjectsHistory.SplitCompound(aParent, aUsed, aNotUsed);
+      anObjectsHistory.splitCompound(aParent, aUsed, aNotUsed);
       aShapesToAdd.insert(aShapesToAdd.end(), aNotUsed.begin(), aNotUsed.end());
 
       // add unused shapes of compounds/compsolids to the history,
       // to avoid treating them as unused later when constructing a compound containing
       // the result of Smash and all unused sub-shapes of multi-level compounds
       for (ListOfShape::iterator anIt = aNotUsed.begin(); anIt != aNotUsed.end(); ++anIt)
-        anObjectsHistory.AddObject(*anIt);
+        anObjectsHistory.addObject(*anIt);
     }
   }
 
index 58b3784e933ceca8d75408aa84dbfe381128a56d..9c348199b3b9f2aa3bb571002395635f1b796991 100644 (file)
@@ -64,23 +64,23 @@ void FeaturesPlugin_Partition::initAttributes()
 //=================================================================================================
 void FeaturesPlugin_Partition::execute()
 {
-  ObjectHierarchy anObjects;
+  GeomAPI_ShapeHierarchy anObjects;
   ListOfShape aPlanes;
 
   // Getting objects.
   processAttribute(BASE_OBJECTS_ID(), anObjects, aPlanes);
-  if(anObjects.IsEmpty()) {
+  if(anObjects.empty()) {
     static const std::string aFeatureError = "Error: No objects for partition.";
     setError(aFeatureError);
     return;
   }
 
-  ListOfShape aBaseObjects = anObjects.Objects();
+  ListOfShape aBaseObjects = anObjects.objects();
   aBaseObjects.insert(aBaseObjects.end(), aPlanes.begin(), aPlanes.end());
 
   // resize planes to the bounding box of operated shapes
   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
-  resizePlanes(anObjects.Objects(), aPlanes, aMakeShapeList);
+  resizePlanes(anObjects.objects(), aPlanes, aMakeShapeList);
 
   // cut unused solids of composolids from the objects of partition
   ListOfShape aTargetObjects, anUnusedSubs;
@@ -147,7 +147,7 @@ void FeaturesPlugin_Partition::execute()
     }
 
     GeomShapePtr aResultCompound =
-      keepUnusedSubsOfCompound(aFirstShape, anObjects, ObjectHierarchy(), aMakeShapeList);
+      keepUnusedSubsOfCompound(aFirstShape, anObjects, GeomAPI_ShapeHierarchy(), aMakeShapeList);
 
     if (anIt.more()) {
       if (aResultCompound->shapeType() != GeomAPI_Shape::COMPOUND) {
@@ -234,7 +234,7 @@ static bool cutSubs(ListOfShape& theSubsToCut,
 }
 
 bool FeaturesPlugin_Partition::cutSubs(
-    FeaturesPlugin_Partition::ObjectHierarchy& theHierarchy,
+    GeomAPI_ShapeHierarchy& theHierarchy,
     ListOfShape& theUsed,
     ListOfShape& theNotUsed,
     std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
@@ -243,14 +243,14 @@ bool FeaturesPlugin_Partition::cutSubs(
   theUsed.clear();
   theNotUsed.clear();
 
-  ObjectHierarchy::Iterator anIt = theHierarchy.Begin();
+  GeomAPI_ShapeHierarchy::iterator anIt = theHierarchy.begin();
 
   // compose a set of tools for the CUT operation:
   // find the list of unused subs of the first argument or use itself
   ListOfShape aToolsForUsed, aToolsForUnused;
-  GeomShapePtr aFirstArgument = theHierarchy.Parent(*anIt, false);
+  GeomShapePtr aFirstArgument = theHierarchy.parent(*anIt, false);
   if (aFirstArgument && aFirstArgument->shapeType() == GeomAPI_Shape::COMPSOLID) {
-    theHierarchy.SplitCompound(aFirstArgument, theUsed, aToolsForUsed);
+    theHierarchy.splitCompound(aFirstArgument, theUsed, aToolsForUsed);
     theNotUsed = aToolsForUsed;
   }
   else {
@@ -261,13 +261,13 @@ bool FeaturesPlugin_Partition::cutSubs(
 
   // cut subs
   bool isOk = true;
-  for (++anIt; anIt != theHierarchy.End() && isOk; ++anIt) {
+  for (++anIt; anIt != theHierarchy.end() && isOk; ++anIt) {
     ListOfShape aUsed, aNotUsed;
 
-    GeomShapePtr aParent = theHierarchy.Parent(*anIt, false);
+    GeomShapePtr aParent = theHierarchy.parent(*anIt, false);
     if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID) {
-      aParent = theHierarchy.Parent(*anIt); // get parent once again to mark its subs as processed
-      theHierarchy.SplitCompound(aParent, aUsed, aNotUsed);
+      aParent = theHierarchy.parent(*anIt); // get parent once again to mark its subs as processed
+      theHierarchy.splitCompound(aParent, aUsed, aNotUsed);
     }
     else
       aUsed.push_back(*anIt);
index b358831d0285bafaced16ff9fac42241a69e5161..5c15c52856f4f5027e67c3c9f886ed953f4635e7 100644 (file)
@@ -73,7 +73,7 @@ private:
   /// Cut all of unused subs of compsolids by the full compsolid of the first selected object,
   /// and vice versa, cut all objects of Partition by not used subs of the first selected object.
   /// Store results of operation to the separated lists of shapes.
-  bool cutSubs(ObjectHierarchy& theHierarchy,
+  bool cutSubs(GeomAPI_ShapeHierarchy& theHierarchy,
                ListOfShape& theUsed,
                ListOfShape& theNotUsed,
                std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
index 0a3107b76e53358230c38cc835e6045f1ab9f1a6..2c658cd907face37d6f95bcc703de83a38507954 100644 (file)
@@ -48,14 +48,14 @@ void FeaturesPlugin_Union::initAttributes()
 //=================================================================================================
 void FeaturesPlugin_Union::execute()
 {
-  ObjectHierarchy anObjects;
+  GeomAPI_ShapeHierarchy anObjects;
   ListOfShape anEmptyList;
 
   // Getting objects.
   if (!processAttribute(BASE_OBJECTS_ID(), anObjects, anEmptyList))
     return;
 
-  if(anObjects.Objects().size() < 2) {
+  if(anObjects.objects().size() < 2) {
     setError("Error: Not enough objects for operation. Should be at least 2.");
     return;
   }
@@ -69,15 +69,15 @@ void FeaturesPlugin_Union::execute()
 
   // Fuse objects.
   bool isOk = true;
-  for (ObjectHierarchy::Iterator anObjectsIt = anObjects.Begin();
-       anObjectsIt != anObjects.End() && isOk;
+  for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
+       anObjectsIt != anObjects.end() && isOk;
        ++anObjectsIt) {
     GeomShapePtr anObject = *anObjectsIt;
-    GeomShapePtr aParent = anObjects.Parent(anObject, false);
+    GeomShapePtr aParent = anObjects.parent(anObject, false);
 
     if (aParent && aParent->shapeType() <= GeomAPI_Shape::COMPSOLID) {
       // get parent once again to mark it and the subs as processed
-      aParent = anObjects.Parent(anObject);
+      aParent = anObjects.parent(anObject);
       // compsolid handling
       isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_FUSE,
                               anObjects, aParent, anEmptyList, anEmptyList,
@@ -111,7 +111,8 @@ void FeaturesPlugin_Union::execute()
   }
   else {
     // merge hierarchies of compounds containing objects and tools
-    aShape = keepUnusedSubsOfCompound(aCIt.current(), anObjects, ObjectHierarchy(), aMakeShapeList);
+    aShape = keepUnusedSubsOfCompound(aCIt.current(), anObjects, GeomAPI_ShapeHierarchy(),
+                                      aMakeShapeList);
     for (aCIt.next(); aCIt.more(); aCIt.next()) {
       std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
       aBuilder->add(aShape, aCIt.current());
@@ -121,7 +122,7 @@ void FeaturesPlugin_Union::execute()
 
   // Store result and naming.
   std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
-  ListOfShape anObjectsList = anObjects.Objects();
+  ListOfShape anObjectsList = anObjects.objects();
   aResultBody->storeModified(anObjectsList.front(), aShape);
 
   for(ListOfShape::const_iterator anIter = anObjectsList.begin();
index bba9645aa9e90f81ceff04cc4fa35eed3d512423..34a459fd73037d092573cd66b6a11538ec2feaea 100644 (file)
@@ -89,22 +89,8 @@ void FeaturesPlugin_VersionedBoolean::initVersion(const std::string& theVersion,
 }
 
 //=================================================================================================
-void FeaturesPlugin_VersionedBoolean::parentForShape(const GeomShapePtr& theShape,
-                                            const ResultPtr& theContext,
-                                            ObjectHierarchy& theShapesHierarchy)
-{
-  ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(theContext);
-  if (aResCompSolidPtr.get()) {
-    std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
-    if (aContextShape->shapeType() <= GeomAPI_Shape::COMPSOLID) {
-      theShapesHierarchy.AddParent(theShape, aContextShape);
-      parentForShape(aContextShape, aResCompSolidPtr, theShapesHierarchy);
-    }
-  }
-}
-
 bool FeaturesPlugin_VersionedBoolean::processAttribute(const std::string& theAttributeName,
-                                              ObjectHierarchy& theObjects,
+                                              GeomAPI_ShapeHierarchy& theObjects,
                                               ListOfShape& thePlanesList)
 {
   AttributeSelectionListPtr anObjectsSelList = selectionList(theAttributeName);
@@ -122,10 +108,10 @@ bool FeaturesPlugin_VersionedBoolean::processAttribute(const std::string& theAtt
         return false;
     }
 
-    theObjects.AddObject(anObject);
+    theObjects.addObject(anObject);
 
     ResultPtr aContext = anObjectAttr->context();
-    parentForShape(anObject, aContext, theObjects);
+    ModelAPI_Tools::fillShapeHierarchy(anObject, aContext, theObjects);
   }
   return true;
 }
@@ -224,7 +210,7 @@ bool FeaturesPlugin_VersionedBoolean::processObject(
 //=================================================================================================
 bool FeaturesPlugin_VersionedBoolean::processCompsolid(
     const GeomAlgoAPI_Tools::BOPType theBooleanType,
-    ObjectHierarchy& theCompsolidHierarchy,
+    GeomAPI_ShapeHierarchy& theCompsolidHierarchy,
     const GeomShapePtr& theCompsolid,
     const ListOfShape& theTools,
     const ListOfShape& thePlanes,
@@ -235,7 +221,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid(
 {
   ListOfShape aUsedInOperationSolids;
   ListOfShape aNotUsedSolids;
-  theCompsolidHierarchy.SplitCompound(theCompsolid, aUsedInOperationSolids, aNotUsedSolids);
+  theCompsolidHierarchy.splitCompound(theCompsolid, aUsedInOperationSolids, aNotUsedSolids);
 
   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
 
@@ -260,7 +246,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid(
 
   // Add result to not used solids from compsolid.
   if (!aNotUsedSolids.empty()) {
-    theCompsolidHierarchy.MarkProcessed(aNotUsedSolids);
+    theCompsolidHierarchy.markProcessed(aNotUsedSolids);
 
     ListOfShape aShapesToAdd = aNotUsedSolids;
     aShapesToAdd.push_back(aBoolAlgo->shape());
@@ -319,7 +305,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid(
 //=================================================================================================
 bool FeaturesPlugin_VersionedBoolean::processCompound(
     const GeomAlgoAPI_Tools::BOPType theBooleanType,
-    ObjectHierarchy& theCompoundHierarchy,
+    GeomAPI_ShapeHierarchy& theCompoundHierarchy,
     const GeomShapePtr& theCompound,
     const ListOfShape& theTools,
     int& theResultIndex,
@@ -329,7 +315,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompound(
 {
   ListOfShape aUsedInOperationShapes;
   ListOfShape aNotUsedShapes;
-  theCompoundHierarchy.SplitCompound(theCompound, aUsedInOperationShapes, 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.
@@ -352,7 +338,7 @@ bool FeaturesPlugin_VersionedBoolean::processCompound(
 
   // Add result to not used shape from compound.
   if (!aNotUsedShapes.empty()) {
-    theCompoundHierarchy.MarkProcessed(aNotUsedShapes);
+    theCompoundHierarchy.markProcessed(aNotUsedShapes);
 
     ListOfShape aShapesForResult = aNotUsedShapes;
     if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
@@ -408,13 +394,13 @@ bool FeaturesPlugin_VersionedBoolean::processCompound(
 //==================================================================================================
 GeomShapePtr FeaturesPlugin_VersionedBoolean::keepUnusedSubsOfCompound(
     const GeomShapePtr& theResult,
-    const ObjectHierarchy& theObjectsHierarchy,
-    const ObjectHierarchy& theToolsHierarchy,
+    const GeomAPI_ShapeHierarchy& theObjectsHierarchy,
+    const GeomAPI_ShapeHierarchy& theToolsHierarchy,
     std::shared_ptr<GeomAlgoAPI_MakeShapeList> theMakeShapeList)
 {
   ListOfShape aCompounds;
-  theObjectsHierarchy.CompoundsOfUnusedObjects(aCompounds);
-  theToolsHierarchy.CompoundsOfUnusedObjects(aCompounds);
+  theObjectsHierarchy.compoundsOfUnusedObjects(aCompounds);
+  theToolsHierarchy.compoundsOfUnusedObjects(aCompounds);
 
   GeomShapePtr aResultShape = theResult;
   if (!aCompounds.empty()) {
@@ -450,235 +436,3 @@ void FeaturesPlugin_VersionedBoolean::resizePlanes(
     *anIt = aTool;
   }
 }
-
-//=================================================================================================
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddObject(const GeomShapePtr& theObject)
-{
-  myObjects.push_back(theObject);
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddParent(const GeomShapePtr& theShape,
-                                                                 const GeomShapePtr& theParent)
-{
-  myParent[theShape] = theParent;
-
-  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_VersionedBoolean::ObjectHierarchy::Parent(const GeomShapePtr& theShape,
-                                                                      bool theMarkProcessed)
-{
-  MapShapeToParent::const_iterator aFound = myParent.find(theShape);
-  GeomShapePtr aParent;
-  if (aFound != myParent.end()) {
-    aParent = aFound->second;
-    if (theMarkProcessed) {
-      // mark the parent and all its subs as processed by Boolean algorithm
-      myProcessedObjects.insert(aParent);
-      const ListOfShape& aSubs = mySubshapes[myParentIndices[aParent]].second;
-      for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
-        myProcessedObjects.insert(*anIt);
-    }
-  }
-  return aParent;
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::MarkProcessed(const GeomShapePtr& theShape)
-{
-  myProcessedObjects.insert(theShape);
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::MarkProcessed(const ListOfShape& theShapes)
-{
-  for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
-    MarkProcessed(*anIt);
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::ObjectsByType(
-    ListOfShape& theShapesByType,
-    ListOfShape& theOtherShapes,
-    const GeomAPI_Shape::ShapeType theMinType,
-    const GeomAPI_Shape::ShapeType theMaxType) const
-{
-  if (theMinType > theMaxType)
-    return ObjectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
-
-  // no need to select objects if whole range is specified
-  if (theMinType == GeomAPI_Shape::COMPOUND && theMaxType == GeomAPI_Shape::SHAPE) {
-    theShapesByType.insert(theShapesByType.end(), myObjects.begin(), myObjects.end());
-    return;
-  }
-
-  for (ListOfShape::const_iterator anIt = myObjects.begin(); anIt != myObjects.end(); ++anIt) {
-    GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
-    if (aType >= theMinType && aType <= theMaxType)
-      theShapesByType.push_back(*anIt);
-    else
-      theOtherShapes.push_back(*anIt);
-  }
-}
-
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::SplitCompound(
-    const GeomShapePtr& theCompShape,
-    ListOfShape& theUsed,
-    ListOfShape& theNotUsed) const
-{
-  theUsed.clear();
-  theNotUsed.clear();
-
-  MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
-  if (aFoundIndex == myParentIndices.end())
-    return; // no such shape
-
-  theUsed = mySubshapes[aFoundIndex->second].second;
-  SetOfShape aSubsSet;
-  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);
-  }
-}
-
-bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::IsEmpty() const
-{
-  return myObjects.empty();
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::CompoundsOfUnusedObjects(
-    ListOfShape& theDestination) const
-{
-  SetOfShape aUsedObjects = myProcessedObjects;
-  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_VersionedBoolean::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(aResult, aCompound);
-        isResultEmpty = false;
-      }
-    }
-  }
-  return isResultEmpty ? GeomShapePtr() : aResult;
-}
-
-
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Begin()
-{
-  return Iterator(this);
-}
-
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::End()
-{
-  return Iterator(this, false);
-}
-
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::Iterator(
-    FeaturesPlugin_VersionedBoolean::ObjectHierarchy* theHierarchy, bool isBegin)
-  : myHierarchy(theHierarchy)
-{
-  if (isBegin) {
-    myObject = myHierarchy->myObjects.begin();
-    SkipAlreadyProcessed();
-  } else
-    myObject = myHierarchy->myObjects.end();
-}
-
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::SkipAlreadyProcessed()
-{
-  while (myObject != myHierarchy->myObjects.end() &&
-         myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
-    ++myObject;
-}
-
-bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator==(
-    const Iterator& theOther) const
-{
-  return myObject == theOther.myObject;
-}
-
-bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator!=(
-    const Iterator& theOther) const
-{
-  return !operator==(theOther);
-}
-
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator&
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator++()
-{
-  ++myObject;
-  SkipAlreadyProcessed();
-  return *this;
-}
-
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator++(int)
-{
-  Iterator aCurrent;
-  aCurrent.myHierarchy = myHierarchy;
-  aCurrent.myObject = myObject;
-
-  // increase iterator
-  operator++();
-
-  return aCurrent;
-}
-
-GeomShapePtr FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator*() const
-{
-  myHierarchy->myProcessedObjects.insert(*myObject);
-  return *myObject;
-}
index 098509c3c4842a85aab0afd590119efc428896de..074a59bcea526b52fbe4978177bfbe21100141bc 100644 (file)
@@ -23,6 +23,7 @@
 #include "FeaturesPlugin.h"
 #include "FeaturesPlugin_Tools.h"
 
+#include <GeomAPI_ShapeHierarchy.h>
 #include <GeomAlgoAPI_Tools.h>
 
 #include <ModelAPI_Feature.h>
@@ -55,92 +56,9 @@ protected:
                    const std::shared_ptr<ModelAPI_Attribute> theToolsAttr
                             = std::shared_ptr<ModelAPI_Attribute>());
 
-  /// Auxiliary class to store hierarchy of Boolean operation objects/tools
-  /// and their parent shapes (compounds or compsolids)
-  class ObjectHierarchy {
-    typedef std::pair<GeomShapePtr, ListOfShape> ShapeAndSubshapes;
-    typedef std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator> MapShapeToParent;
-    typedef std::map<GeomShapePtr, size_t, GeomAPI_Shape::Comparator> MapShapeToIndex;
-    typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShape;
-
-    ListOfShape myObjects; ///< list of objects/tools of Boolean operation
-    MapShapeToParent myParent; ///< refer a shape to compound/compsolid containing it
-    /// indices of compounds/compsolids to keep the order of parent shapes
-    /// corresponding to the order of objects
-    MapShapeToIndex  myParentIndices;
-    /// list of shape and its subshapes stored according to the index of parent shape
-    std::vector<ShapeAndSubshapes> mySubshapes;
-
-    SetOfShape myProcessedObjects;
-
-  public:
-    /// Add object of Boolean opration
-    void AddObject(const GeomShapePtr& theObject);
-
-    /// Maps shape and its parent
-    void AddParent(const GeomShapePtr& theShape, const GeomShapePtr& theParent);
-
-    /// Return parent shape for the given, or empty if it is a high-level shape.
-    /// By default, the parent and all its subshapes are marked as processed for further skip.
-    GeomShapePtr Parent(const GeomShapePtr& theShape, bool theMarkProcessed = true);
-
-    /// Marke the shape as already processed
-    void MarkProcessed(const GeomShapePtr& theShape);
-    /// Marke list ofshapes as already processed
-    void MarkProcessed(const ListOfShape& theShapes);
-
-    /// Split compound/compsolid shape for subshapes selected for Boolean operation and the other.
-    void SplitCompound(const GeomShapePtr& theCompShape,
-                       ListOfShape& theUsed,
-                       ListOfShape& theNotUsed) const;
-
-    /// Generates the list of top-level compounds, which contain the objects of Boolean operation.
-    /// The generated list will contain only shapes unused during the Boolean operation.
-    void CompoundsOfUnusedObjects(ListOfShape& theDestination) const;
-
-    /// Return \c true if there is no object in hierarchy
-    bool IsEmpty() const;
-
-    /// Return list of objects
-    const ListOfShape& Objects() const { return myObjects; }
-    /// Separate objects of the given range of types and all other objects
-    void ObjectsByType(ListOfShape& theShapesByType, ListOfShape& theOtherShapes,
-        const GeomAPI_Shape::ShapeType theMinType = GeomAPI_Shape::COMPOUND,
-        const GeomAPI_Shape::ShapeType theMaxType = GeomAPI_Shape::SHAPE) const;
-
-  private:
-    GeomShapePtr collectUnusedSubs(const GeomShapePtr theTopLevelCompound,
-                                   const SetOfShape& theUsed) const;
-
-  public:
-    class Iterator {
-      friend class ObjectHierarchy;
-
-      ObjectHierarchy* myHierarchy;
-      ListOfShape::iterator myObject;
-
-      Iterator() {}
-      Iterator(ObjectHierarchy* theHierarchy, bool isBegin = true);
-
-      void SkipAlreadyProcessed();
-
-    public:
-      bool operator==(const Iterator&) const;
-      bool operator!=(const Iterator&) const;
-
-      Iterator& operator++();
-      Iterator  operator++(int);
-
-      GeomShapePtr operator*() const;
-    };
-
-    Iterator Begin();
-    Iterator End();
-  };
-
   /// Process SelectionList attribute and fill the objects hierarchy.
   bool processAttribute(const std::string& theAttributeName,
-                        ObjectHierarchy& theObjects,
+                        GeomAPI_ShapeHierarchy& theObjects,
                         ListOfShape& thePlanesList);
 
   /// Perform Boolean operation of the object with the tools.
@@ -161,7 +79,7 @@ protected:
   /// is added to this compound, and corresponding ResultBody is not generated.
   /// \return \c false if something went wrong
   bool processCompsolid(const GeomAlgoAPI_Tools::BOPType theBooleanType,
-                        ObjectHierarchy& theCompsolidHierarchy,
+                        GeomAPI_ShapeHierarchy& theCompsolidHierarchy,
                         const GeomShapePtr& theCompsolid,
                         const ListOfShape& theTools,
                         const ListOfShape& thePlanes,
@@ -175,7 +93,7 @@ protected:
   /// is added to this compound, and corresponding ResultBody is not generated.
   /// \return \c false if something went wrong
   bool processCompound(const GeomAlgoAPI_Tools::BOPType theBooleanType,
-                       ObjectHierarchy& theCompoundHierarchy,
+                       GeomAPI_ShapeHierarchy& theCompoundHierarchy,
                        const GeomShapePtr& theCompound,
                        const ListOfShape& theTools,
                        int& theResultIndex,
@@ -193,14 +111,9 @@ protected:
   /// into a single compound and add the result of the FUSE operation.
   GeomShapePtr keepUnusedSubsOfCompound(
       const GeomShapePtr& theResult,
-      const ObjectHierarchy& theObjectsHierarchy,
-      const ObjectHierarchy& theToolsHierarchy,
+      const GeomAPI_ShapeHierarchy& theObjectsHierarchy,
+      const GeomAPI_ShapeHierarchy& theToolsHierarchy,
       std::shared_ptr<GeomAlgoAPI_MakeShapeList> theMakeShapeList);
-
-private:
-  void parentForShape(const GeomShapePtr& theShape,
-                      const std::shared_ptr<ModelAPI_Result>& theContext,
-                      ObjectHierarchy& theShapesHierarchy);
 };
 
 #endif
index 267c703a9c5f5160db59c157b4f30ccf0fe22a99..4b3c816daaf11e37c831e3c8fdd5a24cef7f11d4 100644 (file)
@@ -70,6 +70,7 @@ SET(PROJECT_HEADERS
     GeomAPI_Torus.h
     GeomAPI_Box.h
     GeomAPI_WireExplorer.h
+    GeomAPI_ShapeHierarchy.h
 )
 
 SET(PROJECT_SOURCES
@@ -118,6 +119,7 @@ SET(PROJECT_SOURCES
     GeomAPI_Torus.cpp
     GeomAPI_Box.cpp
     GeomAPI_WireExplorer.cpp
+    GeomAPI_ShapeHierarchy.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/GeomAPI/GeomAPI_ShapeHierarchy.cpp b/src/GeomAPI/GeomAPI_ShapeHierarchy.cpp
new file mode 100644 (file)
index 0000000..87d5c31
--- /dev/null
@@ -0,0 +1,261 @@
+// Copyright (C) 2014-2020  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "GeomAPI_ShapeHierarchy.h"
+
+#include "GeomAPI_ShapeIterator.h"
+
+#include <BRep_Builder.hxx>
+#include <TopoDS_Shape.hxx>
+
+void GeomAPI_ShapeHierarchy::addObject(const GeomShapePtr& theObject)
+{
+  myObjects.push_back(theObject);
+}
+
+void GeomAPI_ShapeHierarchy::addParent(const GeomShapePtr& theShape,
+                                       const GeomShapePtr& theParent)
+{
+  myParent[theShape] = theParent;
+
+  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 GeomAPI_ShapeHierarchy::parent(const GeomShapePtr& theShape,
+                                            bool theMarkProcessed)
+{
+  MapShapeToParent::const_iterator aFound = myParent.find(theShape);
+  GeomShapePtr aParent;
+  if (aFound != myParent.end()) {
+    aParent = aFound->second;
+    if (theMarkProcessed) {
+      // mark the parent and all its subs as processed by Boolean algorithm
+      markProcessed(aParent);
+      const ListOfShape& aSubs = mySubshapes[myParentIndices[aParent]].second;
+      for (ListOfShape::const_iterator anIt = aSubs.begin(); anIt != aSubs.end(); ++anIt)
+        markProcessed(*anIt);
+    }
+  }
+  return aParent;
+}
+
+void GeomAPI_ShapeHierarchy::markProcessed(const GeomShapePtr& theShape)
+{
+  myProcessedObjects.insert(theShape);
+}
+
+void GeomAPI_ShapeHierarchy::markProcessed(const ListOfShape& theShapes)
+{
+  for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
+    markProcessed(*anIt);
+}
+
+void GeomAPI_ShapeHierarchy::objectsByType(
+    ListOfShape& theShapesByType,
+    ListOfShape& theOtherShapes,
+    const GeomAPI_Shape::ShapeType theMinType,
+    const GeomAPI_Shape::ShapeType theMaxType) const
+{
+  if (theMinType > theMaxType)
+    return objectsByType(theShapesByType, theOtherShapes, theMaxType, theMinType);
+
+  // no need to select objects if whole range is specified
+  if (theMinType == GeomAPI_Shape::COMPOUND && theMaxType == GeomAPI_Shape::SHAPE) {
+    theShapesByType.insert(theShapesByType.end(), myObjects.begin(), myObjects.end());
+    return;
+  }
+
+  for (ListOfShape::const_iterator anIt = myObjects.begin(); anIt != myObjects.end(); ++anIt) {
+    GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
+    if (aType >= theMinType && aType <= theMaxType)
+      theShapesByType.push_back(*anIt);
+    else
+      theOtherShapes.push_back(*anIt);
+  }
+}
+
+
+void GeomAPI_ShapeHierarchy::splitCompound(
+    const GeomShapePtr& theCompShape,
+    ListOfShape& theUsed,
+    ListOfShape& theNotUsed) const
+{
+  theUsed.clear();
+  theNotUsed.clear();
+
+  MapShapeToIndex::const_iterator aFoundIndex = myParentIndices.find(theCompShape);
+  if (aFoundIndex == myParentIndices.end())
+    return; // no such shape
+
+  theUsed = mySubshapes[aFoundIndex->second].second;
+  SetOfShape aSubsSet;
+  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);
+  }
+}
+
+bool GeomAPI_ShapeHierarchy::empty() const
+{
+  return myObjects.empty();
+}
+
+void GeomAPI_ShapeHierarchy::compoundsOfUnusedObjects(
+    ListOfShape& theDestination) const
+{
+  SetOfShape aUsedObjects = myProcessedObjects;
+  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);
+    }
+  }
+}
+
+static void addSubShape(GeomShapePtr theTarget, GeomShapePtr theSub)
+{
+  if (!theTarget.get() || !theSub.get())
+    return;
+
+  TopoDS_Shape* aShape = theTarget->implPtr<TopoDS_Shape>();
+  const TopoDS_Shape& aShapeToAdd = theSub->impl<TopoDS_Shape>();
+
+  static BRep_Builder aBuilder;
+  aBuilder.Add(*aShape, aShapeToAdd);
+}
+
+GeomShapePtr GeomAPI_ShapeHierarchy::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
+        addSubShape(aResult, aCurrent);
+        isResultEmpty = false;
+      }
+    } else {
+      GeomShapePtr aCompound = collectUnusedSubs(aCurrent, theUsed);
+      if (aCompound) {
+        addSubShape(aResult, aCompound);
+        isResultEmpty = false;
+      }
+    }
+  }
+  return isResultEmpty ? GeomShapePtr() : aResult;
+}
+
+
+GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::begin()
+{
+  return iterator(this);
+}
+
+GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::end()
+{
+  return iterator(this, false);
+}
+
+GeomAPI_ShapeHierarchy::iterator::iterator(
+    GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin)
+  : myHierarchy(theHierarchy)
+{
+  if (isBegin) {
+    myObject = myHierarchy->myObjects.begin();
+    skipAlreadyProcessed();
+  } else
+    myObject = myHierarchy->myObjects.end();
+}
+
+void GeomAPI_ShapeHierarchy::iterator::skipAlreadyProcessed()
+{
+  while (myObject != myHierarchy->myObjects.end() &&
+         myHierarchy->myProcessedObjects.find(*myObject) != myHierarchy->myProcessedObjects.end())
+    ++myObject;
+}
+
+bool GeomAPI_ShapeHierarchy::iterator::operator==(const iterator& theOther) const
+{
+  return myObject == theOther.myObject;
+}
+
+bool GeomAPI_ShapeHierarchy::iterator::operator!=(const iterator& theOther) const
+{
+  return !operator==(theOther);
+}
+
+GeomAPI_ShapeHierarchy::iterator& GeomAPI_ShapeHierarchy::iterator::operator++()
+{
+  ++myObject;
+  skipAlreadyProcessed();
+  return *this;
+}
+
+GeomAPI_ShapeHierarchy::iterator GeomAPI_ShapeHierarchy::iterator::operator++(int)
+{
+  iterator aCurrent;
+  aCurrent.myHierarchy = myHierarchy;
+  aCurrent.myObject = myObject;
+
+  // increase iterator
+  operator++();
+
+  return aCurrent;
+}
+
+GeomShapePtr GeomAPI_ShapeHierarchy::iterator::operator*() const
+{
+  myHierarchy->markProcessed(*myObject);
+  return *myObject;
+}
diff --git a/src/GeomAPI/GeomAPI_ShapeHierarchy.h b/src/GeomAPI/GeomAPI_ShapeHierarchy.h
new file mode 100644 (file)
index 0000000..538b826
--- /dev/null
@@ -0,0 +1,121 @@
+// Copyright (C) 2014-2020  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef GeomAPI_ShapeHierarchy_H_
+#define GeomAPI_ShapeHierarchy_H_
+
+#include "GeomAPI.h"
+#include "GeomAPI_Shape.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+/// \class GeomAPI_ShapeHierarchy
+/// \ingroup Plugins
+/// \brief Storage for the hierarchy of shapes and their parents (compounds or compsolids)
+class GeomAPI_ShapeHierarchy
+{
+  typedef std::pair<GeomShapePtr, ListOfShape> ShapeAndSubshapes;
+  typedef std::map<GeomShapePtr, GeomShapePtr, GeomAPI_Shape::Comparator> MapShapeToParent;
+  typedef std::map<GeomShapePtr, size_t, GeomAPI_Shape::Comparator> MapShapeToIndex;
+  typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShape;
+
+  ListOfShape myObjects; ///< list of objects of some operation
+  MapShapeToParent myParent; ///< refer a shape to compound/compsolid containing it
+  /// indices of compounds/compsolids to keep the order of parent shapes
+  /// corresponding to the order of objects
+  MapShapeToIndex  myParentIndices;
+  /// list of shape and its subshapes stored according to the index of parent shape
+  std::vector<ShapeAndSubshapes> mySubshapes;
+
+  SetOfShape myProcessedObjects;
+
+public:
+  /// Add an object of the operation (low-level shape in the hierarchy)
+  GEOMAPI_EXPORT void addObject(const GeomShapePtr& theObject);
+
+  /// Store link between shape and its parent.
+  /// Has to be called by high-level algorithm, because the parent compound/compsolid
+  /// is usually stored as a top-level result
+  GEOMAPI_EXPORT void addParent(const GeomShapePtr& theShape, const GeomShapePtr& theParent);
+
+  /// Return parent shape for the given, or empty if it is a high-level shape.
+  /// By default, the parent and all its subshapes are marked as processed for further skip.
+  GEOMAPI_EXPORT GeomShapePtr parent(const GeomShapePtr& theShape, bool theMarkProcessed = true);
+
+  /// Mark the shape as already processed
+  GEOMAPI_EXPORT void markProcessed(const GeomShapePtr& theShape);
+  /// Mark list ofshapes as already processed
+  GEOMAPI_EXPORT void markProcessed(const ListOfShape& theShapes);
+
+  /// Split compound/compsolid shape for subshapes selected for operation and the others.
+  GEOMAPI_EXPORT void splitCompound(const GeomShapePtr& theCompShape,
+                                    ListOfShape& theUsed,
+                                    ListOfShape& theNotUsed) const;
+
+  /// Generates the list of top-level compounds, which exclude the objects of operation.
+  GEOMAPI_EXPORT void compoundsOfUnusedObjects(ListOfShape& theDestination) const;
+
+  /// Return \c true if there is no object in hierarchy
+  GEOMAPI_EXPORT bool empty() const;
+
+  /// Return list of objects
+  const ListOfShape& objects() const { return myObjects; }
+  /// Separate objects of the given range of types and all other objects
+  GEOMAPI_EXPORT void objectsByType(ListOfShape& theShapesByType, ListOfShape& theOtherShapes,
+      const GeomAPI_Shape::ShapeType theMinType = GeomAPI_Shape::COMPOUND,
+      const GeomAPI_Shape::ShapeType theMaxType = GeomAPI_Shape::SHAPE) const;
+
+private:
+  GeomShapePtr collectUnusedSubs(const GeomShapePtr theTopLevelCompound,
+                                 const SetOfShape& theUsed) const;
+
+public:
+  class iterator : public std::iterator<std::forward_iterator_tag, GeomShapePtr>
+  {
+  public:
+    GEOMAPI_EXPORT iterator() {}
+
+  protected:
+    iterator(GeomAPI_ShapeHierarchy* theHierarchy, bool isBegin = true);
+
+    void skipAlreadyProcessed();
+
+  public:
+    GEOMAPI_EXPORT bool operator==(const iterator&) const;
+    GEOMAPI_EXPORT bool operator!=(const iterator&) const;
+
+    GEOMAPI_EXPORT iterator& operator++();
+    GEOMAPI_EXPORT iterator  operator++(int);
+
+    GEOMAPI_EXPORT GeomShapePtr operator*() const;
+
+  private:
+    GeomAPI_ShapeHierarchy* myHierarchy;
+    ListOfShape::iterator myObject;
+
+    friend class GeomAPI_ShapeHierarchy;
+  };
+
+  GEOMAPI_EXPORT iterator begin();
+  GEOMAPI_EXPORT iterator end();
+};
+
+#endif
index 413f52c4ce616edd2c2e4cb49f84f0621dde2737..f77e99951ae430e70d004b73e5b4a641d5ce5ddb 100644 (file)
@@ -38,6 +38,8 @@
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
 
+#include <GeomAPI_ShapeHierarchy.h>
+
 #define RECURSE_TOP_LEVEL 50
 
 //#define DEBUG_REMOVE_FEATURES
@@ -762,6 +764,21 @@ std::set<FeaturePtr> getParents(const FeaturePtr& theFeature)
   return aParents;
 }
 
+void fillShapeHierarchy(const GeomShapePtr& theShape,
+                        const ResultPtr& theContext,
+                        GeomAPI_ShapeHierarchy& theHierarchy)
+{
+  ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(theContext);
+  if (aResCompSolidPtr.get()) {
+    std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
+    if (aContextShape->shapeType() <= GeomAPI_Shape::COMPSOLID) {
+      theHierarchy.addParent(theShape, aContextShape);
+      fillShapeHierarchy(aContextShape, aResCompSolidPtr, theHierarchy);
+    }
+  }
+}
+
+
 void removeResults(const std::list<ResultPtr>& theResults)
 {
   // collect all documents where the results must be removed
index b0af5520bae730e1b3a1252f24df5a358bb42e70..57cdea0c9aff9d25b5a4ae30b4de086bbe034abb 100644 (file)
@@ -30,6 +30,7 @@ class ModelAPI_ResultParameter;
 class ModelAPI_ResultBody;
 
 class GeomAPI_Shape;
+class GeomAPI_ShapeHierarchy;
 
 #include <memory>
 #include <vector>
@@ -206,6 +207,16 @@ MODELAPI_EXPORT std::pair<std::string, bool> getDefaultName(
 MODELAPI_EXPORT std::set<std::shared_ptr<ModelAPI_Feature> >
     getParents(const std::shared_ptr<ModelAPI_Feature>& theFeature);
 
+/*! Store shape and its parent shape to the hierarchy data structure
+ *  \param[in] theShape      the shape to store
+ *  \param[in] theContext    the result (parent shape) for the given shape
+ *  \param[out] theHierarchy container for shape hierarchy
+ */
+MODELAPI_EXPORT void fillShapeHierarchy(
+    const std::shared_ptr<GeomAPI_Shape>& theShape,
+    const std::shared_ptr<ModelAPI_Result>& theContext,
+    GeomAPI_ShapeHierarchy& theHierarchy);
+
 /*! Creates a remove result features with the given results
 */
 MODELAPI_EXPORT void removeResults(const std::list<std::shared_ptr<ModelAPI_Result> >& theResults);