]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
3. Mixed topology: solids, faces, edges and vertices
authordbv <dbv@opencascade.com>
Fri, 5 Feb 2016 14:52:34 +0000 (17:52 +0300)
committerdbv <dbv@opencascade.com>
Fri, 5 Feb 2016 14:53:01 +0000 (17:53 +0300)
Boolean Fuse operation now allow to fuse edges and faces with solids.

12 files changed:
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/boolean_widget.xml
src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp
src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp
src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomValidators/CMakeLists.txt
src/GeomValidators/GeomValidators_BooleanSelection.cpp [new file with mode: 0644]
src/GeomValidators/GeomValidators_BooleanSelection.h [new file with mode: 0644]
src/GeomValidators/GeomValidators_Plugin.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_ResultCompSolid.cpp

index ee767710c25ee08f8ba61412e5e966ed32a43bd5..25f8f3e0dfa3126cb7c0937807edbe30b765f07b 100644 (file)
@@ -73,7 +73,7 @@ void FeaturesPlugin_Boolean::execute()
     return;
   GeomAlgoAPI_Boolean::OperationType aType = (GeomAlgoAPI_Boolean::OperationType)aTypeAttr->value();
 
-  ListOfShape anObjects, aTools;
+  ListOfShape anObjects, aTools, anEdgesAndFaces;
   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
 
   // Getting objects.
@@ -99,7 +99,12 @@ void FeaturesPlugin_Boolean::execute()
         aCompSolidsObjects[aContextShape].push_back(anObject);
       }
     } else {
-      anObjects.push_back(anObject);
+      if(anObject->shapeType() == GeomAPI_Shape::EDGE ||
+         anObject->shapeType() == GeomAPI_Shape::FACE) {
+        anEdgesAndFaces.push_back(anObject);
+      } else {
+        anObjects.push_back(anObject);
+      }
     }
   }
 
@@ -111,7 +116,12 @@ void FeaturesPlugin_Boolean::execute()
     if(!aTool.get()) {
       return;
     }
-    aTools.push_back(aTool);
+    if(aTool->shapeType() == GeomAPI_Shape::EDGE ||
+       aTool->shapeType() == GeomAPI_Shape::FACE) {
+      anEdgesAndFaces.push_back(aTool);
+    } else {
+      aTools.push_back(aTool);
+    }
   }
 
   int aResultIndex = 0;
@@ -225,7 +235,7 @@ void FeaturesPlugin_Boolean::execute()
       break;
     }
     case GeomAlgoAPI_Boolean::BOOL_FUSE: {
-      if((anObjects.size() + aTools.size() + aCompSolidsObjects.size()) < 2) {
+      if((anObjects.size() + aTools.size() + aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
         std::string aFeatureError = "Not enough objects for boolean operation";
         setError(aFeatureError);
         return;
@@ -236,8 +246,8 @@ void FeaturesPlugin_Boolean::execute()
       aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end());
       aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end());
 
-      // Collecting solids from compsolids which will not be modified in boolean operation.
-      ListOfShape aNotUsedSolids;
+      // Collecting solids from compsolids which will not be modified in boolean operation and will be added to result.
+      ListOfShape aShapesToAdd;
       for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator anIt = aCompSolidsObjects.begin();
         anIt != aCompSolidsObjects.end(); anIt++) {
         std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
@@ -254,23 +264,35 @@ void FeaturesPlugin_Boolean::execute()
             }
           }
           if(anIt == aUsedInOperationSolids.end()) {
-            aNotUsedSolids.push_back(aSolidInCompSolid);
+            aShapesToAdd.push_back(aSolidInCompSolid);
           }
         }
       }
 
-      ListOfShape anOriginalSolids = aSolidsToFuse;
-      anOriginalSolids.insert(anOriginalSolids.end(), aNotUsedSolids.begin(), aNotUsedSolids.end());
+      ListOfShape anOriginalShapes = aSolidsToFuse;
+      anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end());
+
+      // Cut edges and faces(if we have any) with solids.
       GeomAlgoAPI_MakeShapeList aMakeShapeList;
       GeomAPI_DataMapOfShapeShape aMapOfShapes;
+      std::shared_ptr<GeomAPI_Shape> aCuttedEdgesAndFaces;
+      if(!anEdgesAndFaces.empty()) {
+        std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces, anOriginalShapes, GeomAlgoAPI_Boolean::BOOL_CUT));
+        if(aCutAlgo->isDone()) {
+          aCuttedEdgesAndFaces = aCutAlgo->shape();
+          aMakeShapeList.appendAlgo(aCutAlgo);
+          aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
+        }
+      }
+      anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
 
       // If we have compsolids then cut with not used solids all others.
-      if(!aNotUsedSolids.empty()) {
+      if(!aShapesToAdd.empty()) {
         aSolidsToFuse.clear();
-        for(ListOfShape::iterator anIt = anOriginalSolids.begin(); anIt != anOriginalSolids.end(); anIt++) {
+        for(ListOfShape::iterator anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) {
           ListOfShape aOneObjectList;
           aOneObjectList.push_back(*anIt);
-          std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(aOneObjectList, aNotUsedSolids, GeomAlgoAPI_Boolean::BOOL_CUT));
+          std::shared_ptr<GeomAlgoAPI_Boolean> aCutAlgo(new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
 
           if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-7) {
             aSolidsToFuse.push_back(aCutAlgo->shape());
@@ -280,39 +302,55 @@ void FeaturesPlugin_Boolean::execute()
         }
       }
 
-      anObjects.clear();
-      anObjects.push_back(aSolidsToFuse.back());
-      aSolidsToFuse.pop_back();
-      aTools = aSolidsToFuse;
+      if(!aSolidsToFuse.empty()) {
+        anObjects.clear();
+        anObjects.push_back(aSolidsToFuse.back());
+        aSolidsToFuse.pop_back();
+        aTools = aSolidsToFuse;
+      }
 
       // Fuse all objects and all tools.
-      std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, aTools, aType));
+      std::shared_ptr<GeomAPI_Shape> aShape;
+      if(anObjects.size() == 1 && aTools.empty()) {
+        aShape = anObjects.front();
+      } else if(anObjects.empty() && aTools.size() == 1) {
+        aShape = aTools.front();
+      } else if((anObjects.size() + aTools.size()) > 1){
+        std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, aTools, aType));
 
-      // Checking that the algorithm worked properly.
-      if(!aFuseAlgo->isDone()) {
-        static const std::string aFeatureError = "Boolean algorithm failed";
-        setError(aFeatureError);
-        return;
-      }
-      if(aFuseAlgo->shape()->isNull()) {
-        static const std::string aShapeError = "Resulting shape is Null";
-        setError(aShapeError);
-        return;
-      }
-      if(!aFuseAlgo->isValid()) {
-        std::string aFeatureError = "Warning: resulting shape is not valid";
-        setError(aFeatureError);
-        return;
-      }
+        // Checking that the algorithm worked properly.
+        if(!aFuseAlgo->isDone()) {
+          static const std::string aFeatureError = "Boolean algorithm failed";
+          setError(aFeatureError);
+          return;
+        }
+        if(aFuseAlgo->shape()->isNull()) {
+          static const std::string aShapeError = "Resulting shape is Null";
+          setError(aShapeError);
+          return;
+        }
+        if(!aFuseAlgo->isValid()) {
+          std::string aFeatureError = "Warning: resulting shape is not valid";
+          setError(aFeatureError);
+          return;
+        }
 
-      std::shared_ptr<GeomAPI_Shape> aShape = aFuseAlgo->shape();
-      aMakeShapeList.appendAlgo(aFuseAlgo);
-      aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
+        aShape = aFuseAlgo->shape();
+        aMakeShapeList.appendAlgo(aFuseAlgo);
+        aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
+      }
 
-      // Add result to not used solids from compsolid (if we have any).
-      if(!aNotUsedSolids.empty()) {
-        aNotUsedSolids.push_back(aShape);
-        std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aNotUsedSolids, true));
+      // Combine result with not used solids from compsolid and edges and faces (if we have any).
+      if(aCuttedEdgesAndFaces.get() && !aCuttedEdgesAndFaces->isNull()) {
+        aShapesToAdd.push_back(aCuttedEdgesAndFaces);
+      } else {
+        aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end());
+      }
+      if(!aShapesToAdd.empty()) {
+        if(aShape.get()) {
+          aShapesToAdd.push_back(aShape);
+        }
+        std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
         if(!aFillerAlgo->isDone()) {
           std::string aFeatureError = "PaveFiller algorithm failed";
           setError(aFeatureError);
@@ -334,8 +372,10 @@ void FeaturesPlugin_Boolean::execute()
         aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
       }
 
+      std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
+      anOriginalShapes.pop_back();
       std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
-      loadNamingDS(aResultBody, anOriginalSolids.front(), anOriginalSolids, aShape, aMakeShapeList, aMapOfShapes);
+      loadNamingDS(aResultBody, aBackShape, anOriginalShapes, aShape, aMakeShapeList, aMapOfShapes);
       setResult(aResultBody, aResultIndex);
       aResultIndex++;
       break;
@@ -365,17 +405,34 @@ void FeaturesPlugin_Boolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> t
     const int aModifyTag = 1;
     const int aDeletedTag = 2;
     const int aSubsolidsTag = 3; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
+    const int anEdgesAndFacesTag = 10000;
 
     theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
 
-    std::string aModName = "Modified";
+    const std::string aModName = "Modified";
+    const std::string aModEName = "Modified_Edge";
+    const std::string aModFName = "Modified_Face";
+
     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
                                                aModifyTag, aModName, theMapOfShapes);
     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDeletedTag);
 
+    int aTag;
+    std::string aName;
     for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
-      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE,
-                                                 aModifyTag, aModName, theMapOfShapes);
+      if((*anIter)->shapeType() == GeomAPI_Shape::EDGE) {
+        aTag = anEdgesAndFacesTag;
+        aName = aModEName;
+      }
+      else if((*anIter)->shapeType() == GeomAPI_Shape::FACE) {
+        aTag = anEdgesAndFacesTag;
+        aName = aModFName;
+      } else {
+        aTag = aModifyTag;
+        aName = aModName;
+      }
+      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, aName == aModEName ? GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE,
+                                                 aTag, aName, theMapOfShapes);
       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
     }
   }
index ad8061acf274dd79eb1ab6820ca21b1b3dd8ed9b..99d5ca6995b05d063fb70a3544c92911d2f159c2 100644 (file)
     label="Main objects"
     icon=""
     tooltip="Select solid objects"
-    type_choice="Solids"
+    type_choice="Solids Objects"
+    use_choice="false"
     concealment="true">
     <validator id="PartSet_DifferentObjects"/>
-    <validator id="GeomValidators_ShapeType" parameters="empty,solid"/>
+    <!--<validator id="GeomValidators_ShapeType" parameters="empty,edge,face,solid"/>-->
+    <validator id="GeomValidators_BooleanSelection"/>
   </multi_selector>
-  <multi_selector id="tool_objects" 
-    label="Tool objects" 
-    icon="" 
+  <multi_selector id="tool_objects"
+    label="Tool objects"
+    icon=""
     tooltip="Select a tool solid"
-    type_choice="Solids"
+    type_choice="Solids Objects"
+    use_choice="false"
     concealment="true" >
     <validator id="PartSet_DifferentObjects"/>
-    <validator id="GeomValidators_ShapeType" parameters="empty,solid"/>
+    <!--<validator id="GeomValidators_ShapeType" parameters="empty,edge,face,solid"/>-->
+    <validator id="GeomValidators_BooleanSelection"/>
   </multi_selector>
   <validator id="GeomValidators_BooleanArguments" parameters="main_objects,tool_objects,bool_type"/>
 </source>
index 166922710c2e4d7ea9c1366fba1c664c9307e36d..a21ac5f04297702f079461ee8e642134d5239984 100644 (file)
@@ -44,7 +44,9 @@ void GeomAPI_DataMapOfShapeShape::merge(const GeomAPI_DataMapOfShapeShape& theDa
 
 void GeomAPI_DataMapOfShapeShape::merge(const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theDataMap)
 {
-  merge(*theDataMap.get());
+  if(theDataMap.get()) {
+    merge(*theDataMap.get());
+  }
 }
 
 bool GeomAPI_DataMapOfShapeShape::isBound (std::shared_ptr<GeomAPI_Shape> theKey)
index 5322a17e574f2cda35773de03e882ea21fb734c7..2fa01fadd233ebf49337a72921f286b9fec114b4 100644 (file)
@@ -8,10 +8,7 @@
 
 #include <GeomAlgoAPI_DFLoader.h>
 
-#include <BRepAlgoAPI_BooleanOperation.hxx>
-#include <BRepAlgoAPI_Common.hxx>
-#include <BRepAlgoAPI_Cut.hxx>
-#include <BRepAlgoAPI_Fuse.hxx>
+#include <BOPAlgo_BOP.hxx>
 #include <TopTools_ListOfShape.hxx>
 
 //=================================================================================================
@@ -47,35 +44,35 @@ void GeomAlgoAPI_Boolean::build(const ListOfShape& theObjects,
   }
 
   // Creating boolean operation.
-  BRepAlgoAPI_BooleanOperation* anOperation;
+  BOPAlgo_BOP* aBuilder = new BOPAlgo_BOP();
   switch (theOperationType) {
     case BOOL_CUT: {
-      anOperation = new BRepAlgoAPI_Cut();
+      aBuilder->SetOperation(BOPAlgo_CUT);
       break;
     }
     case BOOL_FUSE: {
-      anOperation = new BRepAlgoAPI_Fuse();
+      aBuilder->SetOperation(BOPAlgo_FUSE);
       break;
     }
     case BOOL_COMMON: {
-      anOperation = new BRepAlgoAPI_Common();
+      aBuilder->SetOperation(BOPAlgo_COMMON);
       break;
     }
     default: {
       return;
     }
   }
-  this->setImpl(anOperation);
-  this->setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
-  anOperation->SetArguments(anObjects);
-  anOperation->SetTools(aTools);
+  this->setImpl(aBuilder);
+  this->setBuilderType(OCCT_BOPAlgo_Builder);
+  aBuilder->SetArguments(anObjects);
+  aBuilder->SetTools(aTools);
 
   // Building and getting result.
-  anOperation->Build();
-  if(anOperation->IsDone() != Standard_True) {
+  aBuilder->Perform();
+  if(aBuilder->ErrorStatus() != 0) {
     return;
   }
-  TopoDS_Shape aResult = anOperation->Shape();
+  TopoDS_Shape aResult = aBuilder->Shape();
 
   if(aResult.ShapeType() == TopAbs_COMPOUND) {
     aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
index ad20d9eddf723dfdebd14d1a5af8e68294d13f8d..3dd1cb0b0b7fffd70f4918754dee048bacc0e34b 100644 (file)
@@ -12,6 +12,7 @@
 #include <BOPAlgo_Builder.hxx>
 #include <BOPAlgo_PaveFiller.hxx>
 #include <TopoDS_Builder.hxx>
+#include <TopoDS_Iterator.hxx>
 
 //=================================================================================================
 GeomAlgoAPI_PaveFiller::GeomAlgoAPI_PaveFiller(const ListOfShape& theListOfShape, const bool theIsMakeCompSolids)
@@ -26,7 +27,14 @@ void GeomAlgoAPI_PaveFiller::build(const ListOfShape& theListOfShape, const bool
   BOPAlgo_PaveFiller aPaveFiller;
   BOPCol_ListOfShape aListOfShape;
   for(ListOfShape::const_iterator anIt = theListOfShape.cbegin(); anIt != theListOfShape.cend(); anIt++) {
-    aListOfShape.Append((*anIt)->impl<TopoDS_Shape>());
+    const TopoDS_Shape& aShape = (*anIt)->impl<TopoDS_Shape>();
+    if(aShape.ShapeType() == TopAbs_COMPOUND) {
+      for(TopoDS_Iterator anIter(aShape); anIter.More(); anIter.Next()) {
+        aListOfShape.Append(anIter.Value());
+      }
+    } else {
+      aListOfShape.Append(aShape);
+    }
   }
   aPaveFiller.SetArguments(aListOfShape);
   aPaveFiller.Perform();
index de201f61c10e071b8c92d7f475d13483bd123061..852163df3df21b261cf67792238218d01d92946d 100644 (file)
@@ -85,18 +85,28 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape>
     aTA = TopAbs_SOLID;
   }
 
-  // Map subshapes and shapes.
+  // Get free shapes.
   const TopoDS_Shape& aShapesComp = theCompound->impl<TopoDS_Shape>();
-  BOPCol_IndexedDataMapOfShapeListOfShape aMapEF;
-  BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapEF);
-  if(aMapEF.IsEmpty()) {
+  for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) {
+    const TopoDS_Shape& aShape = anIter.Value();
+    if(aShape.ShapeType() > aTA) {
+      std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
+      aGeomShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
+      theFreeShapes.push_back(aGeomShape);
+    }
+  }
+
+  // Map subshapes and shapes.
+  BOPCol_IndexedDataMapOfShapeListOfShape aMapSA;
+  BOPTools::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
+  if(aMapSA.IsEmpty()) {
     return;
   }
 
   // Get all shapes with common subshapes and free shapes.
   NCollection_Map<TopoDS_Shape> aFreeShapes;
   NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
-  for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
+  for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
     const TopoDS_Shape& aShape = anIter.Key();
     BOPCol_ListOfShape& aListOfShape = anIter.ChangeValue();
     if(aListOfShape.IsEmpty()) {
@@ -120,7 +130,7 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr<GeomAPI_Shape>
       aListOfShape.Clear();
       for(NCollection_List<TopoDS_Shape>::Iterator aTempIter(aTempList); aTempIter.More(); aTempIter.Next()) {
         const TopoDS_Shape& aTempShape = aTempIter.Value();
-        for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapEF); anIter.More(); anIter.Next()) {
+        for(BOPCol_IndexedDataMapOfShapeListOfShape::Iterator anIter(aMapSA); anIter.More(); anIter.Next()) {
           BOPCol_ListOfShape& aTempListOfShape = anIter.ChangeValue();
           if(aTempListOfShape.IsEmpty()) {
             continue;
index aa2d4a0215b3016e0f96fac45c5eab34f65cfbac..ceb12b40d975710bb152119ea0c6fdccd7768d59 100644 (file)
@@ -17,6 +17,7 @@ SET(PROJECT_HEADERS
     GeomValidators_Tools.h
     GeomValidators_ZeroOffset.h
     GeomValidators_Different.h
+    GeomValidators_BooleanSelection.h
 )
 
 SET(PROJECT_SOURCES
@@ -33,6 +34,7 @@ SET(PROJECT_SOURCES
     GeomValidators_Tools.cpp
     GeomValidators_ZeroOffset.cpp
     GeomValidators_Different.cpp
+    GeomValidators_BooleanSelection.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -54,4 +56,3 @@ INCLUDE_DIRECTORIES(
 )
 
 INSTALL(TARGETS GeomValidators DESTINATION plugins)
-
diff --git a/src/GeomValidators/GeomValidators_BooleanSelection.cpp b/src/GeomValidators/GeomValidators_BooleanSelection.cpp
new file mode 100644 (file)
index 0000000..f3f6f24
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomValidators_BooleanSelection.cpp
+// Created:     3 Feb 2016
+// Author:      Dmitry Bobylev
+
+#include "GeomValidators_BooleanSelection.h"
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Feature.h>
+
+bool GeomValidators_BooleanSelection::isValid(const AttributePtr& theAttribute,
+                                              const std::list<std::string>& theArguments,
+                                              std::string& theError) const
+{
+  if(!theAttribute.get()) {
+    theError = "Error: empty selection.";
+    return false;
+  }
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  int anOperationType = aFeature->integer("bool_type")->value();
+  AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+    if(!anAttrSelection.get()) {
+      theError = "Error: empty attribute selection.";
+      return false;
+    }
+    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
+    if(!aShape.get()) {
+      ResultPtr aContext = anAttrSelection->context();
+      if(!aContext.get()) {
+        theError = "Error: empty selection context.";
+        return false;
+      }
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
+      if(!aFeature.get()) {
+        theError = "Error: empty feature.";
+        return false;
+      }
+      std::string aFeatureKind = aFeature->getKind();
+      if(aFeatureKind == "Sketch") {
+        theError = "Error: sketch shape is selected, but only objects are acceptable.";
+        return false;
+      }
+      aShape = aContext->shape();
+    }
+    if(!aShape.get()) {
+      theError = "Error: empty shape.";
+      return false;
+    }
+    int aShapeType = aShape->shapeType();
+    if(anOperationType == 1) {
+      // Fuse operation. Allow to select edges, faces and solids.
+      if(aShapeType != GeomAPI_Shape::EDGE &&
+         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 &&
+         aShapeType != GeomAPI_Shape::COMPOUND) {
+        theError = "Error: selected shape has the wrong type.";
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
diff --git a/src/GeomValidators/GeomValidators_BooleanSelection.h b/src/GeomValidators/GeomValidators_BooleanSelection.h
new file mode 100644 (file)
index 0000000..59b5d3c
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomValidators_BooleanSelection.h
+// Created:     3 Feb 2016
+// Author:      Dmitry Bobylev
+
+#ifndef GeomValidators_BooleanSelection_H
+#define GeomValidators_BooleanSelection_H
+
+#include <ModelAPI.h>
+
+#include <ModelAPI_AttributeValidator.h>
+#include <ModelAPI_Attribute.h>
+
+/// \class GeomValidators_ZeroOffset
+/// \ingroup Validators
+/// \brief Validates selection for boolean operation.
+class GeomValidators_BooleanSelection: public ModelAPI_AttributeValidator
+{
+public:
+  /// \return True if the attribute is valid. It checks whether the selection
+  /// is acceptable for boolean operation.
+  /// \param[in] theAttribute an attribute to check.
+  /// \param[in] theArguments a filter parameters.
+  /// \param[out] theError error message.
+  MODELAPI_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+                                       const std::list<std::string>& theArguments,
+                                       std::string& theError) const;
+};
+
+#endif
index 43d997084e133bd6983851d4306f09836179e430..497e0a70a78f344d72543d0b6760e3069ed0dde9 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <GeomValidators_BodyShapes.h>
 #include <GeomValidators_BooleanArguments.h>
+#include <GeomValidators_BooleanSelection.h>
 #include <GeomValidators_ConstructionComposite.h>
 #include <GeomValidators_Different.h>
 #include <GeomValidators_DifferentShapes.h>
@@ -35,6 +36,7 @@ GeomValidators_Plugin::GeomValidators_Plugin()
   aFactory->registerValidator("GeomValidators_PartitionArguments", new GeomValidators_PartitionArguments);
   aFactory->registerValidator("GeomValidators_ShapeType", new GeomValidators_ShapeType);
   aFactory->registerValidator("GeomValidators_ZeroOffset", new GeomValidators_ZeroOffset);
+  aFactory->registerValidator("GeomValidators_BooleanSelection", new GeomValidators_BooleanSelection);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
index 9a8eaa643dbac955e811e76cf12f73d43416117e..1d3b8a4d506d48ef85e711e995ad7c75e8568f93 100755 (executable)
@@ -225,8 +225,11 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theO
         TNaming_Builder aSubBuilder(aShapeLab.FindChild(aTag++));
         aSubBuilder.Generated(aSubIter.Value());
         if(!aName.IsEmpty()) {
+          TCollection_AsciiString aShapeType = aShape.ShapeType() == TopAbs_EDGE ? "_Edge_" :
+                                               aShape.ShapeType() == TopAbs_FACE ? "_Face_" :
+                                               aShape.ShapeType() == TopAbs_SOLID ? "_Solid_" : "_Shape_";
           std::string aSolidName = 
-            (aName + "_Solid_" + TCollection_AsciiString(aTag - theDecomposeSolidsTag)).ToCString(); 
+            (aName + aShapeType + TCollection_AsciiString(aTag - theDecomposeSolidsTag)).ToCString(); 
           std::shared_ptr<Model_Document> aDoc = 
             std::dynamic_pointer_cast<Model_Document>(document());
           aDoc->addNamingName(aSubBuilder.NamedShape()->Label(), aSolidName);
index 8f4523c4580b0dc4cbf2658996bc7e0f0ba8d6ee..87241ee29c474db6a7a3b7d313c673febfc2c24d 100755 (executable)
@@ -171,10 +171,10 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
     bool aWasEmpty = mySubs.empty();
     Model_Objects* anObjects = std::dynamic_pointer_cast<Model_Document>(document())->objects();
     unsigned int aSubIndex = 0;
-    TopExp_Explorer aSolids(aThisShape, TopAbs_SOLID);
-    for(; aSolids.More(); aSolids.Next(), aSubIndex++) {
-      std::shared_ptr<GeomAPI_Shape> aSolidShape(new GeomAPI_Shape);
-      aSolidShape->setImpl(new TopoDS_Shape(aSolids.Current()));
+    TopoDS_Iterator aShapesIter(aThisShape);
+    for(; aShapesIter.More(); aShapesIter.Next(), aSubIndex++) {
+      std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+      aShape->setImpl(new TopoDS_Shape(aShapesIter.Value()));
       ResultBodyPtr aSub;
       if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result
         aSub = anObjects->createBody(this->data(), aSubIndex);
@@ -182,8 +182,8 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr<GeomAPI_Shape>& the
       } else { // just update shape of this result
         aSub = mySubs[aSubIndex];
       }
-      if (!aSolidShape->isEqual(aSub->shape())) {
-        aSub->store(aSolidShape, false);
+      if (!aShape->isEqual(aSub->shape())) {
+        aSub->store(aShape, false);
         aECreator->sendUpdated(aSub, EVENT_DISP);
         aECreator->sendUpdated(aSub, EVENT_UPD);
       }