Salome HOME
Task 3.2. Concealment into multi-level Compounds
authorazv <azv@opencascade.com>
Tue, 14 May 2019 12:27:22 +0000 (15:27 +0300)
committerazv <azv@opencascade.com>
Tue, 14 May 2019 12:27:22 +0000 (15:27 +0300)
Update behavior of PARTITION operation to keep hierarchy of compounds.

14 files changed:
src/FeaturesAPI/FeaturesAPI_Partition.cpp
src/FeaturesAPI/FeaturesAPI_Partition.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.h
src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.cpp
src/FeaturesPlugin/FeaturesPlugin_VersionedBoolean.h
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound0.py [deleted file]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_1.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_2.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_3.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_1.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_2.py [new file with mode: 0644]
src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_3.py [new file with mode: 0644]

index 1af34d8300d797959aa43eafa47bf00c791261e2..e0a0186ef0e666123c71ffe71f7e2ce136627442 100644 (file)
@@ -30,11 +30,14 @@ FeaturesAPI_Partition::FeaturesAPI_Partition(const std::shared_ptr<ModelAPI_Feat
 }
 
 //==================================================================================================
-FeaturesAPI_Partition::FeaturesAPI_Partition(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                          const std::list<ModelHighAPI_Selection>& theBaseObjects)
+FeaturesAPI_Partition::FeaturesAPI_Partition(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+    const int theVersion)
 : ModelHighAPI_Interface(theFeature)
 {
   if(initialize()) {
+    fillAttribute(theVersion, theFeature->integer(FeaturesPlugin_Partition::VERSION_ID()));
     setBase(theBaseObjects);
   }
 }
@@ -61,15 +64,22 @@ void FeaturesAPI_Partition::dump(ModelHighAPI_Dumper& theDumper) const
 
   AttributeSelectionListPtr anAttrObjects =
     aBase->selectionList(FeaturesPlugin_Partition::BASE_OBJECTS_ID());
+  AttributeIntegerPtr aVersion =
+    aBase->integer(FeaturesPlugin_Partition::VERSION_ID());
 
-  theDumper << aBase << " = model.addPartition(" << aDocName <<
-    ", " << anAttrObjects << ")" << std::endl;
+  theDumper << aBase << " = model.addPartition(" << aDocName << ", " << anAttrObjects;
+
+  if (aVersion && aVersion->isInitialized())
+    theDumper << ", " << aVersion->value();
+
+  theDumper << ")" << std::endl;
 }
 
 //==================================================================================================
 PartitionPtr addPartition(const std::shared_ptr<ModelAPI_Document>& thePart,
-                          const std::list<ModelHighAPI_Selection>& theBaseObjects)
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                          const int theVersion)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Partition::ID());
-  return PartitionPtr(new FeaturesAPI_Partition(aFeature, theBaseObjects));
+  return PartitionPtr(new FeaturesAPI_Partition(aFeature, theBaseObjects, theVersion));
 }
index 15c7253fbd5ed2e58570863980518b094b9a21fe..07b534972c0f11cd66dad19d49c023f36c161b3a 100644 (file)
@@ -43,7 +43,8 @@ public:
   /// Constructor with values.
   FEATURESAPI_EXPORT
   explicit FeaturesAPI_Partition(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                                 const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                                 const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                 const int theVersion = 0);
 
   /// Destructor.
   FEATURESAPI_EXPORT
@@ -69,6 +70,7 @@ typedef std::shared_ptr<FeaturesAPI_Partition> PartitionPtr;
 /// \brief Create Partition feature.
 FEATURESAPI_EXPORT
 PartitionPtr addPartition(const std::shared_ptr<ModelAPI_Document>& thePart,
-                          const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                          const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                          const int theVersion = 0);
 
 #endif // FeaturesAPI_Partition_H_
index 0e8117970fff393457d3101e8d74351b1cefac05..417760da59877d5533dfa79d2778e820e32619e8 100644 (file)
@@ -486,5 +486,10 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestBooleanSplit_MultiLevelCompound_v0_2.py
                TestBooleanSplit_MultiLevelCompound_v20190506_1.py
                TestBooleanSplit_MultiLevelCompound_v20190506_2.py
-               TestPartition_MultiLevelCompound0.py
+               TestPartition_MultiLevelCompound_v0_1.py
+               TestPartition_MultiLevelCompound_v0_2.py
+               TestPartition_MultiLevelCompound_v0_3.py
+               TestPartition_MultiLevelCompound_v20190506_1.py
+               TestPartition_MultiLevelCompound_v20190506_2.py
+               TestPartition_MultiLevelCompound_v20190506_3.py
 )
index 7c29a3efe222bf6a1cb075e989aebb72d59a8e65..83a87047e5e809af4e0ee14d817b16ea5588a684 100644 (file)
@@ -36,6 +36,7 @@
 #include <GeomAlgoAPI_MakeShapeCustom.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Partition.h>
+#include <GeomAlgoAPI_ShapeBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_Tools.h>
 
 #include <list>
 #include <sstream>
 
-typedef std::list<std::pair<GeomShapePtr, ListOfShape> > CompsolidSubs;
-
-static void pullObjectsAndPlanes(const AttributeSelectionListPtr& theSelectedList,
-                                 CompsolidSubs& theObjects, ListOfShape& thePlanes);
-
-static void resizePlanes(const CompsolidSubs& theObjects, ListOfShape& thePlanes,
-                         std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList);
-
-static void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed);
-
-static bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed,
-                          std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
-                          std::string& theError);
+static const int THE_PARTITION_VERSION_1 = 20190506;
 
 
 //=================================================================================================
@@ -71,50 +60,42 @@ FeaturesPlugin_Partition::FeaturesPlugin_Partition()
 void FeaturesPlugin_Partition::initAttributes()
 {
   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+  initVersion(THE_PARTITION_VERSION_1, selectionList(BASE_OBJECTS_ID()));
 }
 
 //=================================================================================================
 void FeaturesPlugin_Partition::execute()
 {
-  CompsolidSubs anObjects;
+  ObjectHierarchy anObjects;
   ListOfShape aPlanes;
 
   // Getting objects.
-  pullObjectsAndPlanes(selectionList(BASE_OBJECTS_ID()), anObjects, aPlanes);
-  if(anObjects.empty()) {
+  processAttribute(BASE_OBJECTS_ID(), anObjects, aPlanes);
+  if(anObjects.IsEmpty()) {
     static const std::string aFeatureError = "Error: No objects for partition.";
     setError(aFeatureError);
     return;
   }
 
-  ListOfShape aBaseObjects;
-  for (CompsolidSubs::iterator anIt = anObjects.begin(); anIt != anObjects.end(); ++anIt)
-    aBaseObjects.insert(aBaseObjects.end(), anIt->second.begin(), anIt->second.end());
+  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, aPlanes, aMakeShapeList);
+  resizePlanes(anObjects.Objects(), aPlanes, aMakeShapeList);
 
   // cut unused solids of composolids from the objects of partition
-  CompsolidSubs anUnusedSubs;
-  unusedSubsOfComposolid(anObjects, anUnusedSubs);
-  for (CompsolidSubs::iterator anIt = anUnusedSubs.begin(); anIt != anUnusedSubs.end(); ++anIt)
-    aBaseObjects.insert(aBaseObjects.end(), anIt->second.begin(), anIt->second.end());
-
+  ListOfShape aTargetObjects, anUnusedSubs;
   std::string aError;
-  if (!cutUnusedSubs(anObjects, anUnusedSubs, aMakeShapeList, aError)) {
+  if (!cutSubs(anObjects, aTargetObjects, anUnusedSubs, aMakeShapeList, aError)) {
     setError(aError);
     return;
   }
+  aBaseObjects.insert(aBaseObjects.end(), anUnusedSubs.begin(), anUnusedSubs.end());
 
-  // perform partition first time to split target solids
-  ListOfShape aTargetObjects;
-  for (CompsolidSubs::iterator anIt = anObjects.begin(); anIt != anObjects.end(); ++anIt)
-    aTargetObjects.insert(aTargetObjects.end(), anIt->second.begin(), anIt->second.end());
-
+  // perform partition first time to split target solids by planes
   std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo(
-    new GeomAlgoAPI_Partition(aTargetObjects, aPlanes));
+      new GeomAlgoAPI_Partition(aTargetObjects, aPlanes));
 
   // Checking that the algorithm worked properly.
   if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), aError)) {
@@ -129,8 +110,7 @@ void FeaturesPlugin_Partition::execute()
     // second pass of a partition to split shared faces of compsolids
     aTargetObjects.clear();
     aTargetObjects.push_back(aResultShape);
-    for (CompsolidSubs::iterator anIt = anUnusedSubs.begin(); anIt != anUnusedSubs.end(); ++anIt)
-      aTargetObjects.insert(aTargetObjects.end(), anIt->second.begin(), anIt->second.end());
+    aTargetObjects.insert(aTargetObjects.end(), anUnusedSubs.begin(), anUnusedSubs.end());
 
     aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aTargetObjects, ListOfShape()));
 
@@ -145,13 +125,41 @@ void FeaturesPlugin_Partition::execute()
   }
 
   int aResultIndex = 0;
-  if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
-    for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) {
-      storeResult(aBaseObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex);
+
+  int aPartitionVersion = version();
+  if (aPartitionVersion < THE_PARTITION_VERSION_1) {
+    // default behaviours of Partition
+    if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+      for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) {
+        storeResult(aBaseObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex);
+        ++aResultIndex;
+      }
+    } else {
+      storeResult(aBaseObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex);
       ++aResultIndex;
     }
-  } else {
-    storeResult(aBaseObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex);
+  }
+  else {
+    // merge hierarchies of compounds containing objects and tools
+    GeomShapePtr aFirstShape = aResultShape;
+    GeomAPI_ShapeIterator anIt;
+    if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+      anIt = GeomAPI_ShapeIterator(aResultShape);
+      aFirstShape = anIt.current();
+      anIt.next();
+    }
+
+    GeomShapePtr aResultCompound =
+      keepUnusedSubsOfCompound(aFirstShape, anObjects, ObjectHierarchy(), aMakeShapeList);
+
+    if (anIt.more()) {
+      std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
+      for (; anIt.more(); anIt.next())
+        aBuilder->add(aResultCompound, anIt.current());
+      aMakeShapeList->appendAlgo(aBuilder);
+    }
+
+    storeResult(aBaseObjects, aPlanes, aResultCompound, aMakeShapeList, aResultIndex);
     ++aResultIndex;
   }
 
@@ -197,160 +205,75 @@ void FeaturesPlugin_Partition::storeResult(
 }
 
 
-//=================     Auxiliary functions     ===================================================
-
-static CompsolidSubs::iterator findOrAdd(CompsolidSubs& theList, const GeomShapePtr& theCompsolid)
-{
-  CompsolidSubs::iterator aFound = theList.begin();
-  for (; aFound != theList.end(); ++aFound)
-    if (aFound->first == theCompsolid)
-      break;
-  if (aFound == theList.end()) {
-    theList.push_back(std::pair<GeomShapePtr, ListOfShape>(theCompsolid, ListOfShape()));
-    aFound = --theList.end();
-  }
-  return aFound;
-}
-
-void pullObjectsAndPlanes(const AttributeSelectionListPtr& theSelectedList,
-                          CompsolidSubs& theObjects, ListOfShape& thePlanes)
-{
-  std::map<ResultBodyPtr, GeomShapePtr> aMapCompsolidShape;
-
-  int aSize = theSelectedList->size();
-  for (int anIndex = 0; anIndex < aSize; ++anIndex) {
-    AttributeSelectionPtr anObjectAttr = theSelectedList->value(anIndex);
-    ResultPtr aContext = anObjectAttr->context();
-    GeomShapePtr anObject = anObjectAttr->value();
-    if (anObject) {
-      GeomShapePtr anOwnerShape = anObject;
-      // check the result is a compsolid and store all used subs in a single list
-      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
-      if (aResCompSolidPtr && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
-        std::map<ResultBodyPtr, GeomShapePtr>::const_iterator
-            aFound = aMapCompsolidShape.find(aResCompSolidPtr);
-        if (aFound != aMapCompsolidShape.end())
-          anOwnerShape = aFound->second;
-        else {
-          anOwnerShape = aResCompSolidPtr->shape();
-          aMapCompsolidShape[aResCompSolidPtr] = anOwnerShape;
-        }
-      }
-
-      CompsolidSubs::iterator aFound = findOrAdd(theObjects, anOwnerShape);
-      aFound->second.push_back(anObject);
-    }
-    else {
-      // It could be a construction plane.
-      thePlanes.push_back(anObjectAttr->context()->shape());
-    }
-  }
-}
-
-void resizePlanes(const CompsolidSubs& theObjects, ListOfShape& thePlanes,
-                  std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList)
-{
-  ListOfShape aSolidsInOperation;
-  for (CompsolidSubs::const_iterator anIt = theObjects.begin(); anIt != theObjects.end(); ++anIt)
-    aSolidsInOperation.insert(aSolidsInOperation.end(), anIt->second.begin(), anIt->second.end());
-
-  std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
-      GeomAlgoAPI_ShapeTools::getBoundingBox(aSolidsInOperation, 1.0);
-
-  ListOfShape aPlanesCopy = thePlanes;
-  thePlanes.clear();
-
-  // Resize planes to fit in bounding box
-  for (ListOfShape::const_iterator anIt = aPlanesCopy.begin(); anIt != aPlanesCopy.end(); ++anIt) {
-    GeomShapePtr aPlane = *anIt;
-    GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
-    std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(new GeomAlgoAPI_MakeShapeCustom);
-    aMkShCustom->addModified(aPlane, aTool);
-    theMakeShapeList->appendAlgo(aMkShCustom);
-    thePlanes.push_back(aTool);
-  }
-}
-
-void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed)
-{
-  for (CompsolidSubs::const_iterator aCSIt = theObjects.begin();
-       aCSIt != theObjects.end(); ++aCSIt) {
-    if (aCSIt->first->shapeType() != GeomAPI_Shape::COMPSOLID)
-      continue;
-
-    // check the compsolid is selected
-    if (aCSIt->second.size() == 1 && aCSIt->first->isEqual(aCSIt->second.front()))
-      continue;
-
-    // process all sub-solids of compsolid
-    ListOfShape aNotUsedSolids;
-    for (GeomAPI_ShapeExplorer anExp(aCSIt->first, GeomAPI_Shape::SOLID);
-         anExp.more(); anExp.next()) {
-      GeomShapePtr aSolidInCompSolid = anExp.current();
-      ListOfShape::const_iterator anIt = aCSIt->second.begin();
-      for (; anIt != aCSIt->second.end(); ++anIt)
-        if (aSolidInCompSolid->isEqual(*anIt))
-          break;
-
-      if (anIt == aCSIt->second.end())
-        aNotUsedSolids.push_back(aSolidInCompSolid);
-    }
-
-    if (!aNotUsedSolids.empty())
-      theNotUsed.push_back(std::pair<GeomShapePtr, ListOfShape>(aCSIt->first, aNotUsedSolids));
-  }
-}
+//=================================================================================================
 
-static bool cutSubs(const GeomShapePtr& theFirstArgument,
-                    CompsolidSubs& theSubsToCut,
+static bool cutSubs(ListOfShape& theSubsToCut,
                     const ListOfShape& theTools,
                     std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
                     std::string& theError)
 {
-  if (theTools.empty())
+  if (theSubsToCut.empty() || theTools.empty())
     return true;
 
-  std::shared_ptr<GeomAlgoAPI_MakeShape> aCutAlgo;
-
-  for (CompsolidSubs::iterator aUIt= theSubsToCut.begin(); aUIt != theSubsToCut.end(); ++aUIt) {
-    if (aUIt->first == theFirstArgument)
-      continue; // no need to split unused subs of the first compsolid
-
-    // cut from current list of solids
-    aCutAlgo.reset(
-        new GeomAlgoAPI_Boolean(aUIt->second, theTools, GeomAlgoAPI_Tools::BOOL_CUT));
-    if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, "", theError))
-      return false;
-    theMakeShapeList->appendAlgo(aCutAlgo);
-
-    // update list of un-selected objects of the partition
-    GeomAPI_Shape::ShapeType aType = aUIt->second.front()->shapeType();
-    aUIt->second.clear();
-    for (GeomAPI_ShapeExplorer anExp(aCutAlgo->shape(), aType); anExp.more(); anExp.next())
-      aUIt->second.push_back(anExp.current());
-  }
+  // cut from current list of solids
+  std::shared_ptr<GeomAlgoAPI_MakeShape> aCutAlgo(
+      new GeomAlgoAPI_Boolean(theSubsToCut, theTools, GeomAlgoAPI_Tools::BOOL_CUT));
+  if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, "", theError))
+    return false;
+  theMakeShapeList->appendAlgo(aCutAlgo);
+
+  // update list of un-selected objects of the partition
+  GeomAPI_Shape::ShapeType aType = theSubsToCut.front()->shapeType();
+  theSubsToCut.clear();
+  for (GeomAPI_ShapeExplorer anExp(aCutAlgo->shape(), aType); anExp.more(); anExp.next())
+    theSubsToCut.push_back(anExp.current());
   return true;
 }
 
-bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed,
-                   std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
-                   std::string& theError)
+bool FeaturesPlugin_Partition::cutSubs(
+    FeaturesPlugin_Partition::ObjectHierarchy& theHierarchy,
+    ListOfShape& theUsed,
+    ListOfShape& theNotUsed,
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
+    std::string& theError)
 {
-  GeomShapePtr aFirstArgument = theObjects.front().first;
+  theUsed.clear();
+  theNotUsed.clear();
+
+  ObjectHierarchy::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;
-  CompsolidSubs::iterator aUIt = theNotUsed.begin();
-  for (; aUIt != theNotUsed.end(); ++aUIt)
-    if (aUIt->first == aFirstArgument) {
-      aToolsForUsed.insert(aToolsForUsed.end(), aUIt->second.begin(), aUIt->second.end());
-      break;
-    }
-  ListOfShape aToolsForUnused;
+  ListOfShape aToolsForUsed, aToolsForUnused;
+  GeomShapePtr aFirstArgument = theHierarchy.Parent(*anIt);
+  if (aFirstArgument && aFirstArgument->shapeType() == GeomAPI_Shape::COMPSOLID) {
+    theHierarchy.SplitCompound(aFirstArgument, theUsed, aToolsForUsed);
+    theNotUsed = aToolsForUsed;
+  }
+  else {
+    aFirstArgument = *anIt;
+    theUsed.push_back(aFirstArgument);
+  }
   aToolsForUnused.push_back(aFirstArgument);
 
   // cut subs
-  return cutSubs(aFirstArgument, theObjects, aToolsForUsed, theMakeShapeList, theError)
-      && cutSubs(aFirstArgument, theNotUsed, aToolsForUnused, theMakeShapeList, theError);
+  bool isOk = true;
+  for (; anIt != theHierarchy.End() && isOk; ++anIt) {
+    ListOfShape aUsed, aNotUsed;
+
+    GeomShapePtr aParent = theHierarchy.Parent(*anIt);
+    if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID)
+      theHierarchy.SplitCompound(aParent, aUsed, aNotUsed);
+    else
+      aUsed.push_back(*anIt);
+
+    isOk = ::cutSubs(aUsed, aToolsForUsed, theMakeShapeList, theError)
+        && ::cutSubs(aNotUsed, aToolsForUnused, theMakeShapeList, theError);
+    if (isOk) {
+      theUsed.insert(theUsed.end(), aUsed.begin(), aUsed.end());
+      theNotUsed.insert(theNotUsed.end(), aNotUsed.begin(), aNotUsed.end());
+    }
+  }
+
+  return isOk;
 }
index 08269203fba50bac715bb82f0ef5c3e8891c8503..aee69380b230c82534e5913aac6f9fc85e18e463 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef FeaturesPlugin_Partition_H_
 #define FeaturesPlugin_Partition_H_
 
-#include "FeaturesPlugin.h"
+#include "FeaturesPlugin_VersionedBoolean.h"
 #include <ModelAPI_Feature.h>
 
 #include <GeomAlgoAPI_Partition.h>
@@ -29,7 +29,7 @@
 /// \ingroup Plugins
 /// \brief Feature for applying of Partition operations on Shapes. Partition makes conjunctional
 /// faces of solids as shared. The result of partitions is a compsolid.
-class FeaturesPlugin_Partition : public ModelAPI_Feature
+class FeaturesPlugin_Partition : public FeaturesPlugin_VersionedBoolean
 {
 public:
   /// Feature kind.
@@ -69,6 +69,15 @@ private:
                    const GeomShapePtr theResultShape,
                    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
                    const int theIndex = 0);
+
+  /// 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,
+               ListOfShape& theUsed,
+               ListOfShape& theNotUsed,
+               std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
+               std::string& theError);
 };
 
 #endif
index ba7d81ba10fde9a70dc34be77d59341be6fdd247..9021a192f5a6ae0f620e2143893c2cc2388e7af7 100644 (file)
@@ -121,20 +121,11 @@ bool FeaturesPlugin_VersionedBoolean::processObject(
   std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
   GeomShapePtr aResShape;
 
-  std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
-      GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
-
   // Resize planes.
   ListOfShape aToolsWithPlanes = theTools;
-  for (ListOfShape::const_iterator anIt = thePlanes.begin(); anIt != thePlanes.end(); ++anIt) {
-    GeomShapePtr aPlane = *anIt;
-    GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
-    std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
-        new GeomAlgoAPI_MakeShapeCustom);
-    aMkShCustom->addModified(aPlane, aTool);
-    aMakeShapeList->appendAlgo(aMkShCustom);
-    aToolsWithPlanes.push_back(aTool);
-  }
+  ListOfShape aPlanesCopy = thePlanes;
+  resizePlanes(aListWithObject, aPlanesCopy, aMakeShapeList);
+  aToolsWithPlanes.insert(aToolsWithPlanes.end(), aPlanesCopy.begin(), aPlanesCopy.end());
 
   if (theBooleanType == GeomAlgoAPI_Tools::BOOL_PARTITION)
     aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
@@ -222,21 +213,11 @@ bool FeaturesPlugin_VersionedBoolean::processCompsolid(
 
   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
 
-  std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
-      GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
-
   // Resize planes.
   ListOfShape aToolsWithPlanes = theTools;
-  for (ListOfShape::const_iterator anIt = thePlanes.begin(); anIt != thePlanes.end(); ++anIt)
-  {
-    GeomShapePtr aPlane = *anIt;
-    GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
-    std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(
-      new GeomAlgoAPI_MakeShapeCustom);
-    aMkShCustom->addModified(aPlane, aTool);
-    aMakeShapeList->appendAlgo(aMkShCustom);
-    aToolsWithPlanes.push_back(aTool);
-  }
+  ListOfShape aPlanesCopy = thePlanes;
+  resizePlanes(aUsedInOperationSolids, aPlanesCopy, aMakeShapeList);
+  aToolsWithPlanes.insert(aToolsWithPlanes.end(), aPlanesCopy.begin(), aPlanesCopy.end());
 
   std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
   if (theBooleanType == GeomAlgoAPI_Tools::BOOL_PARTITION)
@@ -431,6 +412,29 @@ GeomShapePtr FeaturesPlugin_VersionedBoolean::keepUnusedSubsOfCompound(
   return aResultShape;
 }
 
+//=================================================================================================
+void FeaturesPlugin_VersionedBoolean::resizePlanes(
+    const ListOfShape& theObjects,
+    ListOfShape& thePlanes,
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList)
+{
+  if (thePlanes.empty())
+    return;
+
+  std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
+      GeomAlgoAPI_ShapeTools::getBoundingBox(theObjects, 1.0);
+
+  // Resize planes to fit in bounding box
+  for (ListOfShape::iterator anIt = thePlanes.begin(); anIt != thePlanes.end(); ++anIt) {
+    GeomShapePtr aPlane = *anIt;
+    GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
+    std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(new GeomAlgoAPI_MakeShapeCustom);
+    aMkShCustom->addModified(aPlane, aTool);
+    theMakeShapeList->appendAlgo(aMkShCustom);
+    *anIt = aTool;
+  }
+}
+
 //=================================================================================================
 int FeaturesPlugin_VersionedBoolean::version()
 {
@@ -449,7 +453,7 @@ void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddObject(const GeomShape
 }
 
 void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddParent(const GeomShapePtr& theShape,
-                                                        const GeomShapePtr& theParent)
+                                                                 const GeomShapePtr& theParent)
 {
   myParent[theShape] = theParent;
 
@@ -465,7 +469,7 @@ void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::AddParent(const GeomShape
 }
 
 GeomShapePtr FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Parent(const GeomShapePtr& theShape,
-                                                             bool theMarkProcessed)
+                                                                      bool theMarkProcessed)
 {
   MapShapeToParent::const_iterator aFound = myParent.find(theShape);
   GeomShapePtr aParent;
@@ -507,9 +511,10 @@ void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::ObjectsByType(
 }
 
 
-void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::SplitCompound(const GeomShapePtr& theCompShape,
-                                                            ListOfShape& theUsed,
-                                                            ListOfShape& theNotUsed) const
+void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::SplitCompound(
+    const GeomShapePtr& theCompShape,
+    ListOfShape& theUsed,
+    ListOfShape& theNotUsed) const
 {
   theUsed.clear();
   theNotUsed.clear();
@@ -583,7 +588,7 @@ GeomShapePtr FeaturesPlugin_VersionedBoolean::ObjectHierarchy::collectUnusedSubs
     } else {
       GeomShapePtr aCompound = collectUnusedSubs(aCurrent, theUsed);
       if (aCompound) {
-        GeomAlgoAPI_ShapeBuilder::add(theTopLevelCompound, aCompound);
+        GeomAlgoAPI_ShapeBuilder::add(aResult, aCompound);
         isResultEmpty = false;
       }
     }
@@ -592,12 +597,14 @@ GeomShapePtr FeaturesPlugin_VersionedBoolean::ObjectHierarchy::collectUnusedSubs
 }
 
 
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Begin()
+FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator
+FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Begin()
 {
   return Iterator(this);
 }
 
-FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator FeaturesPlugin_VersionedBoolean::ObjectHierarchy::End()
+FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator
+FeaturesPlugin_VersionedBoolean::ObjectHierarchy::End()
 {
   return Iterator(this, false);
 }
@@ -620,12 +627,14 @@ void FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::SkipAlreadyProc
     ++myObject;
 }
 
-bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator==(const Iterator& theOther) const
+bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator==(
+    const Iterator& theOther) const
 {
   return myObject == theOther.myObject;
 }
 
-bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator!=(const Iterator& theOther) const
+bool FeaturesPlugin_VersionedBoolean::ObjectHierarchy::Iterator::operator!=(
+    const Iterator& theOther) const
 {
   return !operator==(theOther);
 }
index 81e662649dec8d79995c9ad761fbf94d55a799ba..97266c7764f1e728c0b83e86adde0f2c7b4a0a25 100644 (file)
@@ -53,8 +53,10 @@ protected:
   /// The version is initialized for newly created features,
   /// not read from previously stored document.
   void initVersion(const int theVersion,
-                   const std::shared_ptr<ModelAPI_Attribute> theObjectsAttr,
-                   const std::shared_ptr<ModelAPI_Attribute> theToolsAttr);
+                   const std::shared_ptr<ModelAPI_Attribute> theObjectsAttr
+                            = std::shared_ptr<ModelAPI_Attribute>(),
+                   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)
@@ -179,6 +181,11 @@ protected:
                        ListOfShape& theResultShapesList,
                        GeomShapePtr theResulCompound = GeomShapePtr());
 
+  /// Resize planes to fit them to the bounding box of the given lins of objects.
+  static void resizePlanes(const ListOfShape& theObjects,
+                           ListOfShape& thePlanes,
+                           std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList);
+
   /// Process unused sub-shapes of compounds.
   /// Keep the compound hierarchy, but merge top-level compounds
   /// into a single compound and add the result of the FUSE operation.
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound0.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound0.py
deleted file mode 100644 (file)
index 68ce6af..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright (C) 2014-2019  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
-#
-
-from SketchAPI import *
-
-from salome.shaper import model
-
-model.begin()
-partSet = model.moduleDocument()
-Part_1 = model.addPart(partSet)
-Part_1_doc = Part_1.document()
-Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 20)
-LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 40, 2)
-LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
-LinearCopy_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
-LinearCopy_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
-LinearCopy_2.result().subResult(1).subResult(0).setColor(0, 0, 255)
-LinearCopy_2.result().subResult(1).subResult(1).setColor(0, 0, 255)
-Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
-SketchLine_1 = Sketch_1.addLine(7, 0, -7, 0)
-SketchLine_2 = Sketch_1.addLine(-7, 0, -7, 5)
-SketchLine_3 = Sketch_1.addLine(-7, 5, 7, 5)
-SketchLine_4 = Sketch_1.addLine(7, 5, 7, 0)
-SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
-SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
-SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
-SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
-SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
-SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
-SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
-SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
-SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
-SketchLine_5 = SketchProjection_1.createdFeature()
-SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_5.result(), 7, True)
-SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_5).startPoint(), SketchLine_1.result())
-SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 14)
-SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 5)
-SketchLine_6 = Sketch_1.addLine(5, 12, -5, 12)
-SketchLine_7 = Sketch_1.addLine(-5, 12, -5, 15)
-SketchLine_8 = Sketch_1.addLine(-5, 15, 5, 15)
-SketchLine_9 = Sketch_1.addLine(5, 15, 5, 12)
-SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
-SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
-SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
-SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
-SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
-SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
-SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_8.result())
-SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
-SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 3)
-SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 10)
-SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_5.result(), 5, True)
-SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchLine_3.result(), 7, True)
-model.do()
-Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 60, 20)
-Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r")], model.selection(), 55, 15)
-LinearCopy_3 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
-AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
-Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
-Compound_1.result().subResult(0).subResult(0).setColor(0, 170, 0)
-Compound_1.result().subResult(0).subResult(1).setColor(0, 170, 0)
-Compound_1.result().subResult(1).subResult(0).setColor(0, 255, 0)
-Compound_1.result().subResult(1).subResult(1).setColor(0, 255, 0)
-Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("COMPOUND", "Compound_1_1_2")])
-model.do()
-model.end()
-
-from GeomAPI import GeomAPI_Shape
-
-model.testNbResults(Partition_1, 1)
-model.testNbSubResults(Partition_1, [10])
-model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [10])
-model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [77])
-model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [328])
-model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [656])
-model.testResultsVolumes(Partition_1, [9335.251534206097858259454369545])
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_1.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_1.py
new file mode 100644 (file)
index 0000000..f639003
--- /dev/null
@@ -0,0 +1,96 @@
+# Copyright (C) 2014-2019  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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 20)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 40, 2)
+LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+LinearCopy_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(1).subResult(0).setColor(0, 0, 255)
+LinearCopy_2.result().subResult(1).subResult(1).setColor(0, 0, 255)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(7, 0, -7, 0)
+SketchLine_2 = Sketch_1.addLine(-7, 0, -7, 5)
+SketchLine_3 = Sketch_1.addLine(-7, 5, 7, 5)
+SketchLine_4 = Sketch_1.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_5 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_5.result(), 7, True)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_5).startPoint(), SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 14)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 5)
+SketchLine_6 = Sketch_1.addLine(5, 12, -5, 12)
+SketchLine_7 = Sketch_1.addLine(-5, 12, -5, 15)
+SketchLine_8 = Sketch_1.addLine(-5, 15, 5, 15)
+SketchLine_9 = Sketch_1.addLine(5, 15, 5, 12)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 3)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 10)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_5.result(), 5, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchLine_3.result(), 7, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 60, 20)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r")], model.selection(), 55, 15)
+LinearCopy_3 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_1.result().subResult(0).subResult(0).setColor(0, 170, 0)
+Compound_1.result().subResult(0).subResult(1).setColor(0, 170, 0)
+Compound_1.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_1.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("COMPOUND", "Compound_1_1_2")])
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [10])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [10])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [77])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [328])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [656])
+model.testResultsVolumes(Partition_1, [9335.251534206097858259454369545])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_2.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_2.py
new file mode 100644 (file)
index 0000000..9c5654f
--- /dev/null
@@ -0,0 +1,121 @@
+# Copyright (C) 2014-2019  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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+SketchCircle_2 = Sketch_1.addCircle(10, 0, 10)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchCircle_2.center())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchCircle_2.center(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 20, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchCircle_3 = Sketch_2.addCircle(0, -7, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.result(), SketchCircle_3.center())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_3.results()[1], 10)
+SketchConstraintDistanceVertical_1 = Sketch_2.setVerticalDistance(SketchCircle_3.center(), SketchAPI_Line(SketchLine_2).startPoint(), 7)
+SketchCircle_4 = Sketch_2.addCircle(40, -27, 10)
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchCircle_4.results()[1], SketchCircle_3.results()[1])
+SketchConstraintDistanceHorizontal_2 = Sketch_2.setHorizontalDistance(SketchCircle_3.center(), SketchCircle_4.center(), 40)
+SketchConstraintDistanceVertical_2 = Sketch_2.setVerticalDistance(SketchCircle_4.center(), SketchCircle_3.center(), 20)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), 20, 0)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")])
+Compound_2 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "Compound_1_1"), model.selection("COMPSOLID", "Extrusion_1_1")])
+Compound_2.result().subResult(0).setColor(255, 170, 0)
+Compound_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+Compound_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+Compound_2.result().subResult(1).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(0).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(1).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(2).setColor(0, 85, 255)
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_3 = Sketch_3.addLine(7, 0, -7, 0)
+SketchLine_4 = Sketch_3.addLine(-7, 0, -7, 5)
+SketchLine_5 = Sketch_3.addLine(-7, 5, 7, 5)
+SketchLine_6 = Sketch_3.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_6.result())
+SketchProjection_3 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_7 = SketchProjection_3.createdFeature()
+SketchConstraintDistance_1 = Sketch_3.setDistance(SketchLine_5.endPoint(), SketchLine_7.result(), 7, True)
+SketchConstraintMiddle_1 = Sketch_3.setMiddlePoint(SketchAPI_Line(SketchLine_7).startPoint(), SketchLine_3.result())
+SketchConstraintLength_1 = Sketch_3.setLength(SketchLine_4.result(), 5)
+SketchLine_8 = Sketch_3.addLine(7, 7, -7, 7)
+SketchLine_9 = Sketch_3.addLine(-7, 7, -7, 10)
+SketchLine_10 = Sketch_3.addLine(-7, 10, 7, 10)
+SketchLine_11 = Sketch_3.addLine(7, 10, 7, 7)
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintHorizontal_3 = Sketch_3.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_3 = Sketch_3.setVertical(SketchLine_9.result())
+SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_10.result())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_11.result())
+SketchConstraintCoincidence_12 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchLine_4.result())
+SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_8.startPoint(), SketchLine_6.result())
+SketchConstraintLength_2 = Sketch_3.setLength(SketchLine_9.result(), 3)
+SketchConstraintDistance_2 = Sketch_3.setDistance(SketchLine_9.startPoint(), SketchLine_5.result(), 2, True)
+model.do()
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_6r-SketchLine_5r-SketchLine_4r-SketchLine_3r")], model.selection(), 50, -10)
+Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_11r-SketchLine_10r-SketchLine_9r-SketchLine_8r")], model.selection(), 60, 20)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_4_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_3 = model.addCompound(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_3.result().subResult(0).setColor(0, 170, 0)
+Compound_3.result().subResult(1).setColor(0, 255, 0)
+Compound_3.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_3.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Compound_2_1_1_1"), model.selection("SOLID", "Compound_2_1_2_3"), model.selection("COMPOUND", "Compound_3_1_2")])
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [24])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [24])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [208])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [938])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1876])
+model.testResultsVolumes(Partition_1, [17001.414867225816])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_3.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v0_3.py
new file mode 100644 (file)
index 0000000..f562091
--- /dev/null
@@ -0,0 +1,112 @@
+# Copyright (C) 2014-2019  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
+#
+
+from GeomAPI import GeomAPI_Shape
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 20)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 40, 2)
+LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+LinearCopy_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(1).subResult(0).setColor(0, 0, 255)
+LinearCopy_2.result().subResult(1).subResult(1).setColor(0, 0, 255)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(7, 0, -7, 0)
+SketchLine_2 = Sketch_1.addLine(-7, 0, -7, 5)
+SketchLine_3 = Sketch_1.addLine(-7, 5, 7, 5)
+SketchLine_4 = Sketch_1.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_5 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_5.result(), 7, True)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_5).startPoint(), SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 14)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 5)
+SketchLine_6 = Sketch_1.addLine(5, 12, -5, 12)
+SketchLine_7 = Sketch_1.addLine(-5, 12, -5, 15)
+SketchLine_8 = Sketch_1.addLine(-5, 15, 5, 15)
+SketchLine_9 = Sketch_1.addLine(5, 15, 5, 12)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 3)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 10)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_5.result(), 5, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchLine_3.result(), 7, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 60, 20)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r")], model.selection(), 55, 15)
+LinearCopy_3 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_1.result().subResult(0).subResult(0).setColor(0, 170, 0)
+Compound_1.result().subResult(0).subResult(1).setColor(0, 170, 0)
+Compound_1.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_1.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1_objects = [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("SOLID", "Compound_1_1_2_2"), model.selection("SOLID", "LinearCopy_2_1_2_2"), model.selection("SOLID", "Compound_1_1_1_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
+model.do()
+
+model.testNbResults(Partition_1, 2)
+model.testNbSubResults(Partition_1, [4, 4])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [4, 4])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [25, 27])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [102, 114])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [204, 228])
+model.testResultsVolumes(Partition_1, [7809.218420698664886, 10607.88782061204438])
+
+# change Partition objects
+Partition_1_objects = [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("SOLID", "Compound_1_1_2_2"), model.selection("SOLID", "LinearCopy_2_1_2_2")]
+Partition_1.setBase(Partition_1_objects)
+model.do()
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Partition_1, 2)
+model.testNbSubResults(Partition_1, [4, 0])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [4, 1])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [25, 3])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [102, 6])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [204, 12])
+model.testResultsVolumes(Partition_1, [7809.218420698664886, 6283.185307179586744])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_1.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_1.py
new file mode 100644 (file)
index 0000000..de14905
--- /dev/null
@@ -0,0 +1,96 @@
+# Copyright (C) 2014-2019  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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 20)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 40, 2)
+LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+LinearCopy_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(1).subResult(0).setColor(0, 0, 255)
+LinearCopy_2.result().subResult(1).subResult(1).setColor(0, 0, 255)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(7, 0, -7, 0)
+SketchLine_2 = Sketch_1.addLine(-7, 0, -7, 5)
+SketchLine_3 = Sketch_1.addLine(-7, 5, 7, 5)
+SketchLine_4 = Sketch_1.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_5 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_5.result(), 7, True)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_5).startPoint(), SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 14)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 5)
+SketchLine_6 = Sketch_1.addLine(5, 12, -5, 12)
+SketchLine_7 = Sketch_1.addLine(-5, 12, -5, 15)
+SketchLine_8 = Sketch_1.addLine(-5, 15, 5, 15)
+SketchLine_9 = Sketch_1.addLine(5, 15, 5, 12)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 3)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 10)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_5.result(), 5, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchLine_3.result(), 7, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 60, 20)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r")], model.selection(), 55, 15)
+LinearCopy_3 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_1.result().subResult(0).subResult(0).setColor(0, 170, 0)
+Compound_1.result().subResult(0).subResult(1).setColor(0, 170, 0)
+Compound_1.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_1.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("COMPOUND", "Compound_1_1_2")], 20190506)
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [4])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [15])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [98])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [394])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [788])
+model.testResultsVolumes(Partition_1, [39384.807455744848994])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_2.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_2.py
new file mode 100644 (file)
index 0000000..26e0f56
--- /dev/null
@@ -0,0 +1,121 @@
+# Copyright (C) 2014-2019  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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_1).startPoint(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+SketchCircle_2 = Sketch_1.addCircle(10, 0, 10)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.result(), SketchCircle_2.center())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Line(SketchLine_1).startPoint(), SketchCircle_2.center(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 20, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchCircle_3 = Sketch_2.addCircle(0, -7, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.result(), SketchCircle_3.center())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_3.results()[1], 10)
+SketchConstraintDistanceVertical_1 = Sketch_2.setVerticalDistance(SketchCircle_3.center(), SketchAPI_Line(SketchLine_2).startPoint(), 7)
+SketchCircle_4 = Sketch_2.addCircle(40, -27, 10)
+SketchConstraintEqual_2 = Sketch_2.setEqual(SketchCircle_4.results()[1], SketchCircle_3.results()[1])
+SketchConstraintDistanceHorizontal_2 = Sketch_2.setHorizontalDistance(SketchCircle_3.center(), SketchCircle_4.center(), 40)
+SketchConstraintDistanceVertical_2 = Sketch_2.setVerticalDistance(SketchCircle_4.center(), SketchCircle_3.center(), 20)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), 20, 0)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1"), model.selection("SOLID", "Extrusion_2_2")])
+Compound_2 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "Compound_1_1"), model.selection("COMPSOLID", "Extrusion_1_1")])
+Compound_2.result().subResult(0).setColor(255, 170, 0)
+Compound_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+Compound_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+Compound_2.result().subResult(1).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(0).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(1).setColor(0, 85, 255)
+Compound_2.result().subResult(1).subResult(2).setColor(0, 85, 255)
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_3 = Sketch_3.addLine(7, 0, -7, 0)
+SketchLine_4 = Sketch_3.addLine(-7, 0, -7, 5)
+SketchLine_5 = Sketch_3.addLine(-7, 5, 7, 5)
+SketchLine_6 = Sketch_3.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_6.result())
+SketchProjection_3 = Sketch_3.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_7 = SketchProjection_3.createdFeature()
+SketchConstraintDistance_1 = Sketch_3.setDistance(SketchLine_5.endPoint(), SketchLine_7.result(), 7, True)
+SketchConstraintMiddle_1 = Sketch_3.setMiddlePoint(SketchAPI_Line(SketchLine_7).startPoint(), SketchLine_3.result())
+SketchConstraintLength_1 = Sketch_3.setLength(SketchLine_4.result(), 5)
+SketchLine_8 = Sketch_3.addLine(7, 7, -7, 7)
+SketchLine_9 = Sketch_3.addLine(-7, 7, -7, 10)
+SketchLine_10 = Sketch_3.addLine(-7, 10, 7, 10)
+SketchLine_11 = Sketch_3.addLine(7, 10, 7, 7)
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_11.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_3.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_3.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintHorizontal_3 = Sketch_3.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_3 = Sketch_3.setVertical(SketchLine_9.result())
+SketchConstraintHorizontal_4 = Sketch_3.setHorizontal(SketchLine_10.result())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_11.result())
+SketchConstraintCoincidence_12 = Sketch_3.setCoincident(SketchLine_9.startPoint(), SketchLine_4.result())
+SketchConstraintCoincidence_13 = Sketch_3.setCoincident(SketchLine_8.startPoint(), SketchLine_6.result())
+SketchConstraintLength_2 = Sketch_3.setLength(SketchLine_9.result(), 3)
+SketchConstraintDistance_2 = Sketch_3.setDistance(SketchLine_9.startPoint(), SketchLine_5.result(), 2, True)
+model.do()
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_6r-SketchLine_5r-SketchLine_4r-SketchLine_3r")], model.selection(), 50, -10)
+Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_3/Face-SketchLine_11r-SketchLine_10r-SketchLine_9r-SketchLine_8r")], model.selection(), 60, 20)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_4_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_3 = model.addCompound(Part_1_doc, [model.selection("SOLID", "Extrusion_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_3.result().subResult(0).setColor(0, 170, 0)
+Compound_3.result().subResult(1).setColor(0, 255, 0)
+Compound_3.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_3.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Compound_2_1_1_1"), model.selection("SOLID", "Compound_2_1_2_3"), model.selection("COMPOUND", "Compound_3_1_2")], 20190506)
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [3])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [26])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [217])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [968])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [1936])
+model.testResultsVolumes(Partition_1, [26084.60017440541])
+
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_3.py b/src/FeaturesPlugin/Test/TestPartition_MultiLevelCompound_v20190506_3.py
new file mode 100644 (file)
index 0000000..0007bd6
--- /dev/null
@@ -0,0 +1,110 @@
+# Copyright (C) 2014-2019  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
+#
+
+from GeomAPI import GeomAPI_Shape
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 20)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 40, 2)
+LinearCopy_2 = model.addMultiTranslation(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+LinearCopy_2.result().subResult(0).subResult(0).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(0).subResult(1).setColor(255, 170, 0)
+LinearCopy_2.result().subResult(1).subResult(0).setColor(0, 0, 255)
+LinearCopy_2.result().subResult(1).subResult(1).setColor(0, 0, 255)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(7, 0, -7, 0)
+SketchLine_2 = Sketch_1.addLine(-7, 0, -7, 5)
+SketchLine_3 = Sketch_1.addLine(-7, 5, 7, 5)
+SketchLine_4 = Sketch_1.addLine(7, 5, 7, 0)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_5 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.endPoint(), SketchLine_5.result(), 7, True)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchAPI_Line(SketchLine_5).startPoint(), SketchLine_1.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 14)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 5)
+SketchLine_6 = Sketch_1.addLine(5, 12, -5, 12)
+SketchLine_7 = Sketch_1.addLine(-5, 12, -5, 15)
+SketchLine_8 = Sketch_1.addLine(-5, 15, 5, 15)
+SketchLine_9 = Sketch_1.addLine(5, 15, 5, 12)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_8.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_7.result(), 3)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 10)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.endPoint(), SketchLine_5.result(), 5, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchLine_6.startPoint(), SketchLine_3.result(), 7, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 60, 20)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r")], model.selection(), 55, 15)
+LinearCopy_3 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OY"), 40, 2)
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")], model.selection("EDGE", "PartSet/OZ"), 90, 2)
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPOUND", "LinearCopy_3_1"), model.selection("COMPOUND", "AngularCopy_1_1")])
+Compound_1.result().subResult(0).subResult(0).setColor(0, 170, 0)
+Compound_1.result().subResult(0).subResult(1).setColor(0, 170, 0)
+Compound_1.result().subResult(1).subResult(0).setColor(0, 255, 0)
+Compound_1.result().subResult(1).subResult(1).setColor(0, 255, 0)
+Partition_1_objects = [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("SOLID", "Compound_1_1_2_2"), model.selection("SOLID", "LinearCopy_2_1_2_2"), model.selection("SOLID", "Compound_1_1_1_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+model.do()
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [6])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [12])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [70])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [276])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [552])
+model.testResultsVolumes(Partition_1, [38683.4768556698836619])
+
+# change Partition objects
+Partition_1_objects = [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("SOLID", "Compound_1_1_2_2"), model.selection("SOLID", "LinearCopy_2_1_2_2")]
+Partition_1.setBase(Partition_1_objects)
+model.do()
+
+model.testHaveNamingSubshapes(Partition_1, model, Part_1_doc)
+
+model.end()
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [6])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [10])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.FACE, [52])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.EDGE, [192])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.VERTEX, [384])
+model.testResultsVolumes(Partition_1, [39958.774342237426])
+
+assert(model.checkPythonDump())