Salome HOME
Issue #2306: 1.1.2.3 Fill construction planes
authordbv <dbv@opencascade.com>
Wed, 1 Nov 2017 11:53:13 +0000 (14:53 +0300)
committerdbv <dbv@opencascade.com>
Thu, 23 Nov 2017 11:33:31 +0000 (14:33 +0300)
Now Boolean Fill allows to select construction planes as Tools.

src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_Boolean.h
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/Test/TestBooleanFillWithPlane.py [new file with mode: 0644]

index 0ebd6b158d70fc923d97d8b92b3ebb15e6530f6f..a828b1a94d8f44cc23037b30c1a03a400712bcc7 100644 (file)
@@ -156,6 +156,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestBooleanCompSolids.py
                TestBooleanSmash.py
                TestBooleanFill.py
+               TestBooleanFillWithPlane.py
                TestMultiBoolean.py
                TestSerialBoolean.py
                TestIntersection.py
index b51d76b60079f828e22d108873850259b1bce324..08af8844540ac2689460607338268b5610ccc36a 100644 (file)
 #include <ModelAPI_Tools.h>
 
 #include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_MakeShapeCustom.h>
 #include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Partition.h>
 #include <GeomAlgoAPI_PaveFiller.h>
 #include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAPI_Face.h>
 #include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_ShapeIterator.h>
 
@@ -87,7 +89,7 @@ void FeaturesPlugin_Boolean::execute()
     return;
   OperationType aType = (FeaturesPlugin_Boolean::OperationType)aTypeAttr->value();
 
-  ListOfShape anObjects, aTools, anEdgesAndFaces;
+  ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes;
   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
 
   // Getting objects.
@@ -129,11 +131,12 @@ void FeaturesPlugin_Boolean::execute()
   AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
   for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
     AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
-    std::shared_ptr<GeomAPI_Shape> aTool = aToolAttr->value();
+    GeomShapePtr aTool = aToolAttr->value();
     if(!aTool.get()) {
-      return;
-    }
-    if(aTool->shapeType() == GeomAPI_Shape::EDGE ||
+      // It could be a construction plane.
+      ResultPtr aContext = aToolAttr->context();
+      aPlanes.push_back(aToolAttr->context()->shape());
+    } else if(aTool->shapeType() == GeomAPI_Shape::EDGE ||
        aTool->shapeType() == GeomAPI_Shape::FACE) {
       anEdgesAndFaces.push_back(aTool);
     } else {
@@ -147,7 +150,8 @@ void FeaturesPlugin_Boolean::execute()
     case BOOL_CUT:
     case BOOL_COMMON:
     case BOOL_FILL: {
-      if((anObjects.empty() && aCompSolidsObjects.empty()) || aTools.empty()) {
+      if((anObjects.empty() && aCompSolidsObjects.empty())
+          || (aTools.empty() && aPlanes.empty())) {
         std::string aFeatureError = "Error: Not enough objects for boolean operation.";
         setError(aFeatureError);
         return;
@@ -159,25 +163,46 @@ void FeaturesPlugin_Boolean::execute()
         std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
         ListOfShape aListWithObject;
         aListWithObject.push_back(anObject);
-        GeomAlgoAPI_MakeShape aBoolAlgo;
+        GeomAlgoAPI_MakeShapeList aMakeShapeList;
+        std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
         GeomShapePtr aResShape;
 
         switch(aType) {
           case BOOL_CUT: {
-            aBoolAlgo =
-              GeomAlgoAPI_Boolean(aListWithObject, aTools, GeomAlgoAPI_Boolean::BOOL_CUT);
-            aResShape = aBoolAlgo.shape();
+            aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
+                                                    aTools,
+                                                    GeomAlgoAPI_Boolean::BOOL_CUT));
+            aResShape = aBoolAlgo->shape();
             break;
           }
           case BOOL_COMMON: {
-            aBoolAlgo =
-              GeomAlgoAPI_Boolean(aListWithObject, aTools, GeomAlgoAPI_Boolean::BOOL_COMMON);
-            aResShape = aBoolAlgo.shape();
+            aBoolAlgo.reset(new GeomAlgoAPI_Boolean(aListWithObject,
+                                                    aTools,
+                                                    GeomAlgoAPI_Boolean::BOOL_COMMON));
+            aResShape = aBoolAlgo->shape();
             break;
           }
           case BOOL_FILL: {
-            aBoolAlgo = GeomAlgoAPI_Partition(aListWithObject, aTools);
-            aResShape = aBoolAlgo.shape();
+              std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
+                GeomAlgoAPI_ShapeTools::getBoundingBox(aListWithObject, 1.0);
+
+            // Resize planes.
+            ListOfShape aToolsWithPlanes = aTools;
+            for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
+                                            anIt != aPlanes.cend();
+                                            ++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);
+            }
+
+            aBoolAlgo.reset(new GeomAlgoAPI_Partition(aListWithObject, aToolsWithPlanes));
+            aResShape = aBoolAlgo->shape();
             if(aResShape->shapeType() == GeomAPI_Shape::COMPOUND) {
               int aSubResultsNb = 0;
               GeomAPI_ShapeIterator anIt(aResShape);
@@ -196,7 +221,7 @@ void FeaturesPlugin_Boolean::execute()
         }
 
         // Checking that the algorithm worked properly.
-        if(!aBoolAlgo.isDone()) {
+        if(!aBoolAlgo->isDone()) {
           static const std::string aFeatureError = "Error: Boolean algorithm failed.";
           setError(aFeatureError);
           return;
@@ -206,17 +231,25 @@ void FeaturesPlugin_Boolean::execute()
           setError(aShapeError);
           return;
         }
-        if(!aBoolAlgo.isValid()) {
+        if(!aBoolAlgo->isValid()) {
           std::string aFeatureError = "Error: Resulting shape is not valid.";
           setError(aFeatureError);
           return;
         }
 
+        aMakeShapeList.appendAlgo(aBoolAlgo);
+
         if(GeomAlgoAPI_ShapeTools::volume(aResShape) > 1.e-27) {
           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
             document()->createBody(data(), aResultIndex);
-          loadNamingDS(aResultBody, anObject, aTools, aResShape,
-                       aBoolAlgo, *aBoolAlgo.mapOfSubShapes().get());
+
+          ListOfShape aUsedTools = aTools;
+          if (aType == BOOL_FILL) {
+            aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
+          }
+
+          loadNamingDS(aResultBody, anObject, aUsedTools, aResShape,
+                       aMakeShapeList, *(aBoolAlgo->mapOfSubShapes()), aType == BOOL_FILL);
           setResult(aResultBody, aResultIndex);
           aResultIndex++;
         }
@@ -245,6 +278,7 @@ void FeaturesPlugin_Boolean::execute()
           }
         }
 
+        GeomAlgoAPI_MakeShapeList aMakeShapeList;
         std::shared_ptr<GeomAlgoAPI_MakeShape> aBoolAlgo;
 
         switch(aType) {
@@ -261,7 +295,25 @@ void FeaturesPlugin_Boolean::execute()
             break;
           }
           case BOOL_FILL: {
-            aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aTools));
+            std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
+              GeomAlgoAPI_ShapeTools::getBoundingBox(aUsedInOperationSolids, 1.0);
+
+            // Resize planes.
+            ListOfShape aToolsWithPlanes = aTools;
+            for(ListOfShape::const_iterator anIt = aPlanes.cbegin();
+                                            anIt != aPlanes.cend();
+                                            ++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);
+            }
+
+            aBoolAlgo.reset(new GeomAlgoAPI_Partition(aUsedInOperationSolids, aToolsWithPlanes));
             break;
           }
         }
@@ -283,7 +335,6 @@ void FeaturesPlugin_Boolean::execute()
           return;
         }
 
-        GeomAlgoAPI_MakeShapeList aMakeShapeList;
         aMakeShapeList.appendAlgo(aBoolAlgo);
         GeomAPI_DataMapOfShapeShape aMapOfShapes;
         aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
@@ -309,7 +360,19 @@ void FeaturesPlugin_Boolean::execute()
         if(GeomAlgoAPI_ShapeTools::volume(aResultShape) > 1.e-27) {
           std::shared_ptr<ModelAPI_ResultBody> aResultBody =
             document()->createBody(data(), aResultIndex);
-          loadNamingDS(aResultBody, aCompSolid, aTools, aResultShape, aMakeShapeList, aMapOfShapes);
+
+          ListOfShape aUsedTools = aTools;
+          if (aType == BOOL_FILL) {
+            aUsedTools.insert(aUsedTools.end(), aPlanes.begin(), aPlanes.end());
+          }
+
+          loadNamingDS(aResultBody,
+                       aCompSolid,
+                       aUsedTools,
+                       aResultShape,
+                       aMakeShapeList,
+                       aMapOfShapes,
+                       aType == BOOL_FILL);
           setResult(aResultBody, aResultIndex);
           aResultIndex++;
         }
@@ -626,7 +689,8 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
                                           const ListOfShape& theTools,
                                           const std::shared_ptr<GeomAPI_Shape> theResultShape,
                                           GeomAlgoAPI_MakeShape& theMakeShape,
-                                          GeomAPI_DataMapOfShapeShape& theMapOfShapes)
+                                          GeomAPI_DataMapOfShapeShape& theMapOfShapes,
+                                          const bool theIsStoreAsGenerated)
 {
   //load result
   if(theBaseShape->isEqual(theResultShape)) {
@@ -645,7 +709,7 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     const std::string aModFName = "Modified_Face";
 
     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
-      aModifyTag, aModName, theMapOfShapes, false, false, true);
+      aModifyTag, aModName, theMapOfShapes, false, theIsStoreAsGenerated, true);
     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
                                      GeomAPI_Shape::FACE, aDeletedTag);
 
@@ -666,7 +730,7 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
       }
       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
         aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
-        aTag, aName, theMapOfShapes, false, false, true);
+        aTag, aName, theMapOfShapes, false, theIsStoreAsGenerated, true);
       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
     }
   }
index 726b33846bc0e402630a422f65e8d146d16cdede..d49820686883058d1991b778f8ab14a0f6c6ec4c 100644 (file)
@@ -95,7 +95,8 @@ private:
                     const ListOfShape& theTools,
                     const std::shared_ptr<GeomAPI_Shape> theResultShape,
                     GeomAlgoAPI_MakeShape& theMakeShape,
-                    GeomAPI_DataMapOfShapeShape& theMapOfShapes);
+                    GeomAPI_DataMapOfShapeShape& theMapOfShapes,
+                    const bool theIsStoreAsGenerated = false);
 };
 
 #endif
index acc2b8becfa8d36a29a2f60c8d31a902f08b70c5..fa2ab069581d86172ceeb58b33910474365c4371 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "FeaturesPlugin_Validators.h"
 
+#include "FeaturesPlugin_Boolean.h"
 #include "FeaturesPlugin_Union.h"
 
 #include <Events_InfoMessage.h>
@@ -608,8 +609,11 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
     ResultConstructionPtr aResultConstruction =
       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
     if(aResultConstruction.get()) {
-      theError = "Error: Result construction not allowed for selection.";
-      return false;
+      if (anOperationType != FeaturesPlugin_Boolean::BOOL_FILL
+          || theAttribute->id() != FeaturesPlugin_Boolean::TOOL_LIST_ID()) {
+        theError = "Error: Result construction not allowed for selection.";
+        return false;
+      }
     }
     std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
     GeomShapePtr aContextShape = aContext->shape();
@@ -626,7 +630,7 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
     }
 
     int aShapeType = aShape->shapeType();
-    if(anOperationType == 1) {
+    if(anOperationType == FeaturesPlugin_Boolean::BOOL_FUSE) {
       // Fuse operation. Allow to select edges, faces and solids.
       if(aShapeType != GeomAPI_Shape::EDGE &&
          aShapeType != GeomAPI_Shape::FACE &&
@@ -636,6 +640,14 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
         theError = "Error: Selected shape has the wrong type.";
         return false;
       }
+    } else if (anOperationType == FeaturesPlugin_Boolean::BOOL_FILL) {
+      if(aShapeType != GeomAPI_Shape::FACE &&
+         aShapeType != GeomAPI_Shape::SOLID &&
+         aShapeType != GeomAPI_Shape::COMPSOLID &&
+         aShapeType != GeomAPI_Shape::COMPOUND) {
+        theError = "Error: Selected shape has the wrong type.";
+        return false;
+      }
     } else {
       if(aShapeType != GeomAPI_Shape::SOLID &&
          aShapeType != GeomAPI_Shape::COMPSOLID &&
diff --git a/src/FeaturesPlugin/Test/TestBooleanFillWithPlane.py b/src/FeaturesPlugin/Test/TestBooleanFillWithPlane.py
new file mode 100644 (file)
index 0000000..923b64d
--- /dev/null
@@ -0,0 +1,69 @@
+## Copyright (C) 2014-2017  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<mailto:webmaster.salome@opencascade.com>
+##
+
+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"))
+SketchLine_1 = Sketch_1.addLine(50.45430931454487, 141.3050678403047, -211.8625790259634, 141.3050678403047)
+SketchLine_2 = Sketch_1.addLine(-211.8625790259634, 141.3050678403047, -211.8625790259634, -163.3288837233227)
+SketchLine_3 = Sketch_1.addLine(-211.8625790259634, -163.3288837233227, 50.45430931454487, -163.3288837233227)
+SketchLine_4 = Sketch_1.addLine(50.45430931454487, -163.3288837233227, 50.45430931454487, 141.3050678403047)
+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())
+SketchLine_5 = Sketch_1.addLine(246.5736143115653, 48.78197815871301, -51.09047583637312, 48.78197815871301)
+SketchLine_6 = Sketch_1.addLine(-51.09047583637312, 48.78197815871301, -51.09047583637312, -104.8260668928192)
+SketchLine_7 = Sketch_1.addLine(-51.09047583637312, -104.8260668928192, 246.5736143115653, -104.8260668928192)
+SketchLine_8 = Sketch_1.addLine(246.5736143115653, -104.8260668928192, 246.5736143115653, 48.78197815871301)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.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())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_8.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 100, 0)
+Boolean_1 = model.addFill(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1_2")], [model.selection("FACE", "PartSet/YOZ")])
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Boolean_1_1_4/Modified_3"), model.selection("FACE", "Boolean_1_1_4/Modified_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Boolean_1_1_4/Modified_2"), model.selection("FACE", "Boolean_1_1_4/Modified_4"), model.selection("FACE", "Boolean_1_1_4/Modified_1"), model.selection("FACE", "Boolean_1_1_4/Modified_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_6"), model.selection("FACE", "Boolean_1_1_3/Modified_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_7"), model.selection("FACE", "Boolean_1_1_1/Modified_2"), model.selection("FACE", "Extrusion_1_1/Generated_Face_5"), model.selection("FACE", "Boolean_1_1_4/Modified_4"), model.selection("FACE", "Boolean_1_1_3/Modified_4"), model.selection("FACE", "Extrusion_1_1/Generated_Face_9"), model.selection("FACE", "Boolean_1_1_1/Modified_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_12"), model.selection("FACE", "Extrusion_1_1/Generated_Face_11"), model.selection("FACE", "Boolean_1_1_3/Modified_3"), model.selection("FACE", "Boolean_1_1_3/Modified_2"), model.selection("FACE", "Boolean_1_1_3/Modified_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Boolean_1_1_3/Modified_4"), model.selection("FACE", "Boolean_1_1_4/Modified_Face_1"), model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), model.selection("FACE", "Extrusion_1_1/To_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_2"), model.selection("FACE", "Extrusion_1_1/From_Face_3"), model.selection("FACE", "Extrusion_1_1/Generated_Face_1")])
+model.do()
+model.end()
+
+from GeomAPI import  GeomAPI_Shape
+
+model.testNbResults(Boolean_1, 1)
+model.testNbSubResults(Boolean_1, [4])
+model.testNbSubShapes(Boolean_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Boolean_1, GeomAPI_Shape.FACE, [30])
+model.testNbSubShapes(Boolean_1, GeomAPI_Shape.EDGE, [132])
+model.testNbSubShapes(Boolean_1, GeomAPI_Shape.VERTEX, [264])
+model.testResultsVolumes(Boolean_1, [11003613.329450136050581932067871094])
+
+assert(model.checkPythonDump())