]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'Results_Hierarchy'
authormpv <mikhail.ponikarov@opencascade.com>
Thu, 16 Aug 2018 18:41:52 +0000 (21:41 +0300)
committermpv <mikhail.ponikarov@opencascade.com>
Thu, 16 Aug 2018 18:41:52 +0000 (21:41 +0300)
1  2 
src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp
src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp
src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/Test/TestBooleanCompSolids.py
src/GeomAPI/CMakeLists.txt

index 1d7d14a5f74ba86904db9f125e75061c5f05180d,0000000000000000000000000000000000000000..0319ee264c5ac9eac9d8ebe5a9d194cc59b010c1
mode 100644,000000..100644
--- /dev/null
@@@ -1,374 -1,0 +1,374 @@@
- #include <ModelAPI_ResultCompSolid.h>
 +// 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>
 +//
 +
 +#include "FeaturesPlugin_BooleanFuse.h"
 +
-     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
++#include <ModelAPI_ResultBody.h>
 +#include <ModelAPI_AttributeBoolean.h>
 +#include <ModelAPI_AttributeSelectionList.h>
 +#include <ModelAPI_AttributeString.h>
 +#include <ModelAPI_Session.h>
 +#include <ModelAPI_Tools.h>
 +#include <ModelAPI_Validator.h>
 +
 +#include <GeomAlgoAPI_Boolean.h>
 +#include <GeomAlgoAPI_MakeShapeList.h>
 +#include <GeomAlgoAPI_PaveFiller.h>
 +#include <GeomAlgoAPI_ShapeTools.h>
 +#include <GeomAlgoAPI_UnifySameDomain.h>
 +#include <GeomAPI_ShapeExplorer.h>
 +
 +//==================================================================================================
 +FeaturesPlugin_BooleanFuse::FeaturesPlugin_BooleanFuse()
 +: FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_FUSE)
 +{
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanFuse::initAttributes()
 +{
 +  data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
 +
 +  data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
 +  data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
 +
 +  data()->addAttribute(REMOVE_INTERSECTION_EDGES_ID(), ModelAPI_AttributeBoolean::typeId());
 +
 +  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
 +  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanFuse::execute()
 +{
 +  ListOfShape anObjects, aTools, anEdgesAndFaces, aPlanes;
 +  std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
 +
 +  bool isSimpleCreation = false;
 +
 +  AttributeStringPtr aCreationMethodAttr = string(CREATION_METHOD());
 +  if (aCreationMethodAttr.get()
 +      && aCreationMethodAttr->value() == CREATION_METHOD_SIMPLE()) {
 +    isSimpleCreation = true;
 +  }
 +
 +  // Getting objects.
 +  AttributeSelectionListPtr anObjectsSelList =
 +    selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
 +  for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
 +    AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
 +    std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
 +    if (!anObject.get()) {
 +      return;
 +    }
 +    ResultPtr aContext = anObjectAttr->context();
++    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +    if (!isSimpleCreation
 +        && aResCompSolidPtr.get()
 +        && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) {
 +      std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
 +      std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
 +        anIt = aCompSolidsObjects.begin();
 +      for (; anIt != aCompSolidsObjects.end(); anIt++) {
 +        if (anIt->first->isEqual(aContextShape)) {
 +          aCompSolidsObjects[anIt->first].push_back(anObject);
 +          break;
 +        }
 +      }
 +      if (anIt == aCompSolidsObjects.end()) {
 +        aCompSolidsObjects[aContextShape].push_back(anObject);
 +      }
 +    } else {
 +      if (anObject->shapeType() == GeomAPI_Shape::EDGE
 +          || anObject->shapeType() == GeomAPI_Shape::FACE) {
 +        anEdgesAndFaces.push_back(anObject);
 +      } else {
 +        anObjects.push_back(anObject);
 +      }
 +    }
 +  }
 +
 +  // Getting tools.
 +  if (!isSimpleCreation) {
 +    AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
 +    for (int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
 +      AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
 +      GeomShapePtr aTool = aToolAttr->value();
 +      if (!aTool.get()) {
 +        // 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 {
 +        aTools.push_back(aTool);
 +      }
 +    }
 +  }
 +
 +  if ((anObjects.size() + aTools.size() +
 +    aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) {
 +    std::string aFeatureError = "Error: Not enough objects for boolean operation.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +
 +  // Collecting all solids which will be fused.
 +  ListOfShape aSolidsToFuse;
 +  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 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;
 +    ListOfShape& aUsedInOperationSolids = anIt->second;
 +    aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(),
 +                         aUsedInOperationSolids.end());
 +
 +    // Collect solids from compsolid which will not be modified in boolean operation.
 +    for (GeomAPI_ShapeExplorer
 +         anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
 +      std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
 +      ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
 +      for (; anIt != aUsedInOperationSolids.end(); anIt++) {
 +        if (aSolidInCompSolid->isEqual(*anIt)) {
 +          break;
 +        }
 +      }
 +      if (anIt == aUsedInOperationSolids.end()) {
 +        aShapesToAdd.push_back(aSolidInCompSolid);
 +      }
 +    }
 +  }
 +
 +  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 (!aShapesToAdd.empty()) {
 +    aSolidsToFuse.clear();
 +    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, aShapesToAdd, GeomAlgoAPI_Boolean::BOOL_CUT));
 +
 +      if (GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) {
 +        aSolidsToFuse.push_back(aCutAlgo->shape());
 +        aMakeShapeList.appendAlgo(aCutAlgo);
 +        aMapOfShapes.merge(aCutAlgo->mapOfSubShapes());
 +      }
 +    }
 +  }
 +
 +  if (!aSolidsToFuse.empty()) {
 +    anObjects.clear();
 +    anObjects.push_back(aSolidsToFuse.back());
 +    aSolidsToFuse.pop_back();
 +    aTools = aSolidsToFuse;
 +  }
 +
 +  // Fuse all objects and all tools.
 +  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,
 +      GeomAlgoAPI_Boolean::BOOL_FUSE));
 +
 +    // Checking that the algorithm worked properly.
 +    if (!aFuseAlgo->isDone()) {
 +      static const std::string aFeatureError = "Error: Boolean algorithm failed.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +    if (aFuseAlgo->shape()->isNull()) {
 +      static const std::string aShapeError = "Error: Resulting shape is Null.";
 +      setError(aShapeError);
 +      return;
 +    }
 +    if (!aFuseAlgo->isValid()) {
 +      std::string aFeatureError = "Error: Resulting shape is not valid.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +
 +    aShape = aFuseAlgo->shape();
 +    aMakeShapeList.appendAlgo(aFuseAlgo);
 +    aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
 +  }
 +
 +  // 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 = "Error: PaveFiller algorithm failed.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +    if (aFillerAlgo->shape()->isNull()) {
 +      static const std::string aShapeError = "Error: Resulting shape is Null.";
 +      setError(aShapeError);
 +      return;
 +    }
 +    if (!aFillerAlgo->isValid()) {
 +      std::string aFeatureError = "Error: Resulting shape is not valid.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +
 +    aShape = aFillerAlgo->shape();
 +    aMakeShapeList.appendAlgo(aFillerAlgo);
 +    aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
 +  }
 +
 +  bool isRemoveEdges = false;
 +  AttributeBooleanPtr removeEdgesAttr = boolean(REMOVE_INTERSECTION_EDGES_ID());
 +  if (removeEdgesAttr.get()) {
 +    isRemoveEdges = removeEdgesAttr->value();
 +  }
 +
 +  if (isRemoveEdges) {
 +    std::shared_ptr<GeomAlgoAPI_UnifySameDomain> aUnifyAlgo(
 +      new GeomAlgoAPI_UnifySameDomain(aShape));
 +
 +    if (!aUnifyAlgo->isDone()) {
 +      std::string aFeatureError = "Error: PaveFiller algorithm failed.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +    if (aUnifyAlgo->shape()->isNull()) {
 +      static const std::string aShapeError = "Error: Resulting shape is Null.";
 +      setError(aShapeError);
 +      return;
 +    }
 +    if (!aUnifyAlgo->isValid()) {
 +      std::string aFeatureError = "Error: Resulting shape is not valid.";
 +      setError(aFeatureError);
 +      return;
 +    }
 +
 +    aShape = aUnifyAlgo->shape();
 +    aMakeShapeList.appendAlgo(aUnifyAlgo);
 +    aMapOfShapes.merge(aUnifyAlgo->mapOfSubShapes());
 +  }
 +
 +  int aResultIndex = 0;
 +
 +  std::shared_ptr<GeomAPI_Shape> aBackShape = anOriginalShapes.back();
 +  anOriginalShapes.pop_back();
 +  std::shared_ptr<ModelAPI_ResultBody> aResultBody =
 +    document()->createBody(data(), aResultIndex);
 +  loadNamingDS(aResultBody, aBackShape, anOriginalShapes,
 +               aShape, aMakeShapeList, aMapOfShapes);
 +  setResult(aResultBody, aResultIndex);
 +  aResultIndex++;
 +
 +  // remove the rest results if there were produced in the previous pass
 +  removeResults(aResultIndex);
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanFuse::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
 +                                          const std::shared_ptr<GeomAPI_Shape> theBaseShape,
 +                                          const ListOfShape& theTools,
 +                                          const std::shared_ptr<GeomAPI_Shape> theResultShape,
 +                                          GeomAlgoAPI_MakeShape& theMakeShape,
 +                                          GeomAPI_DataMapOfShapeShape& theMapOfShapes)
 +{
 +  //load result
 +  if (theBaseShape->isEqual(theResultShape)) {
 +    theResultBody->store(theResultShape, false);
 +  } else {
 +    const int aModifyTag = 1;
 +    const int aModifyEdgeTag = 2;
 +    const int aModifyFaceTag = 3;
 +    const int aDeletedTag = 4;
 +    /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
 +    const int aSubsolidsTag = 5;
 +
 +    theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
 +
 +    const std::string aModName = "Modified";
 +    const std::string aModEName = "Modified_Edge";
 +    const std::string aModFName = "Modified_Face";
 +
 +    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
 +                                               aModifyEdgeTag, aModEName, theMapOfShapes, false,
 +                                               false, true);
 +    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
 +                                               aModifyFaceTag, aModFName, theMapOfShapes, false,
 +                                               false, true);
 +    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
 +                                     GeomAPI_Shape::FACE, aDeletedTag);
 +
 +    int aTag;
 +    std::string aName;
 +    for (ListOfShape::const_iterator
 +         anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
 +      if ((*anIter)->shapeType() <= GeomAPI_Shape::FACE) {
 +        aTag = aModifyFaceTag;
 +        aName = aModFName;
 +      } else {
 +        aTag = aModifyEdgeTag;
 +        aName = aModEName;
 +      }
 +      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter,
 +                                                 aName == aModEName ? GeomAPI_Shape::EDGE
 +                                                                    : GeomAPI_Shape::FACE,
 +                                                 aTag, aName, theMapOfShapes, false, false, true);
 +      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
 +    }
 +  }
 +}
index ebc6549588eb11bc4ed6c4f7972e5a76f5cc1049,0000000000000000000000000000000000000000..f0aa745dd3251110493eb09a0aa2b0fe9e202427
mode 100644,000000..100644
--- /dev/null
@@@ -1,306 -1,0 +1,306 @@@
- #include <ModelAPI_ResultCompSolid.h>
 +// 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>
 +//
 +
 +#include "FeaturesPlugin_BooleanSmash.h"
 +
-     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
++#include <ModelAPI_ResultBody.h>
 +#include <ModelAPI_AttributeSelectionList.h>
 +#include <ModelAPI_Tools.h>
 +
 +#include <GeomAlgoAPI_Boolean.h>
 +#include <GeomAlgoAPI_CompoundBuilder.h>
 +#include <GeomAlgoAPI_MakeShapeList.h>
 +#include <GeomAlgoAPI_PaveFiller.h>
 +#include <GeomAlgoAPI_ShapeTools.h>
 +#include <GeomAPI_ShapeExplorer.h>
 +#include <GeomAPI_ShapeIterator.h>
 +
 +//==================================================================================================
 +FeaturesPlugin_BooleanSmash::FeaturesPlugin_BooleanSmash()
 +: FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_SMASH)
 +{
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanSmash::initAttributes()
 +{
 +  data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
 +  data()->addAttribute(TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanSmash::execute()
 +{
 +  ListOfShape anObjects, aTools;
 +  std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
 +
 +  // Getting objects.
 +  AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
 +  for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
 +    AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
 +    std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
 +    if(!anObject.get()) {
 +      return;
 +    }
 +    ResultPtr aContext = anObjectAttr->context();
++    ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +    if (aResCompSolidPtr.get())
 +    {
 +      std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
 +
 +      std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
 +        anIt = aCompSolidsObjects.begin();
 +      for (; anIt != aCompSolidsObjects.end(); anIt++) {
 +        if (anIt->first->isEqual(aContextShape)) {
 +          aCompSolidsObjects[anIt->first].push_back(anObject);
 +          break;
 +        }
 +      }
 +      if (anIt == aCompSolidsObjects.end()) {
 +        aCompSolidsObjects[aContextShape].push_back(anObject);
 +      }
 +
 +    } else {
 +      anObjects.push_back(anObject);
 +    }
 +  }
 +
 +  // Getting tools.
 +  AttributeSelectionListPtr aToolsSelList = selectionList(TOOL_LIST_ID());
 +  for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
 +    AttributeSelectionPtr aToolAttr = aToolsSelList->value(aToolsIndex);
 +    GeomShapePtr aTool = aToolAttr->value();
 +    if(!aTool.get()) {
 +      return;
 +    }
 +    aTools.push_back(aTool);
 +  }
 +
 +  int aResultIndex = 0;
 +
 +  if((anObjects.empty() && aCompSolidsObjects.empty())
 +     || aTools.empty()) {
 +    std::string aFeatureError = "Error: Not enough objects for boolean operation.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +
 +  // List of original shapes for naming.
 +  ListOfShape anOriginalShapes;
 +  anOriginalShapes.insert(anOriginalShapes.end(), anObjects.begin(), anObjects.end());
 +  anOriginalShapes.insert(anOriginalShapes.end(), aTools.begin(), aTools.end());
 +
 +  // Collecting all shapes which will be smashed.
 +  ListOfShape aShapesToSmash;
 +  aShapesToSmash.insert(aShapesToSmash.end(), anObjects.begin(), anObjects.end());
 +
 +  // 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;
 +    ListOfShape& aUsedInOperationSolids = anIt->second;
 +    anOriginalShapes.push_back(aCompSolid);
 +    aShapesToSmash.insert(aShapesToSmash.end(),
 +                          aUsedInOperationSolids.begin(),
 +                          aUsedInOperationSolids.end());
 +
 +    // Collect solids from compsolid which will not be modified in boolean operation.
 +    for (GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID);
 +         anExp.more();
 +         anExp.next())
 +    {
 +      std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
 +      ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
 +      for (; anIt != aUsedInOperationSolids.end(); anIt++) {
 +        if (aSolidInCompSolid->isEqual(*anIt)) {
 +          break;
 +        }
 +      }
 +      if (anIt == aUsedInOperationSolids.end()) {
 +        aShapesToAdd.push_back(aSolidInCompSolid);
 +      }
 +    }
 +  }
 +
 +  GeomAlgoAPI_MakeShapeList aMakeShapeList;
 +  GeomAPI_DataMapOfShapeShape aMapOfShapes;
 +  if (!aShapesToAdd.empty()) {
 +    // Cut objects with not used solids.
 +    std::shared_ptr<GeomAlgoAPI_Boolean> anObjectsCutAlgo(
 +      new GeomAlgoAPI_Boolean(aShapesToSmash,
 +                              aShapesToAdd,
 +                              GeomAlgoAPI_Boolean::BOOL_CUT));
 +
 +    if (GeomAlgoAPI_ShapeTools::volume(anObjectsCutAlgo->shape()) > 1.e-27) {
 +      aShapesToSmash.clear();
 +      aShapesToSmash.push_back(anObjectsCutAlgo->shape());
 +      aMakeShapeList.appendAlgo(anObjectsCutAlgo);
 +      aMapOfShapes.merge(anObjectsCutAlgo->mapOfSubShapes());
 +    }
 +
 +    // Cut tools with not used solids.
 +    std::shared_ptr<GeomAlgoAPI_Boolean> aToolsCutAlgo(
 +      new GeomAlgoAPI_Boolean(aTools,
 +                              aShapesToAdd,
 +                              GeomAlgoAPI_Boolean::BOOL_CUT));
 +
 +    if (GeomAlgoAPI_ShapeTools::volume(aToolsCutAlgo->shape()) > 1.e-27) {
 +      aTools.clear();
 +      aTools.push_back(aToolsCutAlgo->shape());
 +      aMakeShapeList.appendAlgo(aToolsCutAlgo);
 +      aMapOfShapes.merge(aToolsCutAlgo->mapOfSubShapes());
 +    }
 +  }
 +
 +  // Cut objects with tools.
 +  std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo(
 +    new GeomAlgoAPI_Boolean(aShapesToSmash,
 +                            aTools,
 +                            GeomAlgoAPI_Boolean::BOOL_CUT));
 +
 +  // Checking that the algorithm worked properly.
 +  if (!aBoolAlgo->isDone()) {
 +    static const std::string aFeatureError = "Error: Boolean algorithm failed.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +  if (aBoolAlgo->shape()->isNull()) {
 +    static const std::string aShapeError = "Error: Resulting shape is Null.";
 +    setError(aShapeError);
 +    return;
 +  }
 +  if (!aBoolAlgo->isValid()) {
 +    std::string aFeatureError = "Error: Resulting shape is not valid.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +  aMakeShapeList.appendAlgo(aBoolAlgo);
 +  aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes());
 +
 +  // Put all (cut result, tools and not used solids) to PaveFiller.
 +  aShapesToAdd.push_back(aBoolAlgo->shape());
 +  aShapesToAdd.insert(aShapesToAdd.end(), aTools.begin(), aTools.end());
 +
 +  std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
 +    new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
 +  if (!aFillerAlgo->isDone()) {
 +    std::string aFeatureError = "Error: PaveFiller algorithm failed.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +  if (aFillerAlgo->shape()->isNull()) {
 +    static const std::string aShapeError = "Error: Resulting shape is Null.";
 +    setError(aShapeError);
 +    return;
 +  }
 +  if (!aFillerAlgo->isValid()) {
 +    std::string aFeatureError = "Error: Resulting shape is not valid.";
 +    setError(aFeatureError);
 +    return;
 +  }
 +
 +  std::shared_ptr<GeomAPI_Shape> aShape = aFillerAlgo->shape();
 +  aMakeShapeList.appendAlgo(aFillerAlgo);
 +  aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
 +
 +  std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
 +  anOriginalShapes.pop_front();
 +  std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
 +  loadNamingDS(aResultBody,
 +               aFrontShape,
 +               anOriginalShapes,
 +               aShape,
 +               aMakeShapeList,
 +               aMapOfShapes);
 +
 +  setResult(aResultBody, aResultIndex);
 +  aResultIndex++;
 +
 +  // remove the rest results if there were produced in the previous pass
 +  removeResults(aResultIndex);
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_BooleanSmash::loadNamingDS(ResultBodyPtr theResultBody,
 +                                             const GeomShapePtr theBaseShape,
 +                                             const ListOfShape& theTools,
 +                                             const GeomShapePtr theResultShape,
 +                                             GeomAlgoAPI_MakeShape& theMakeShape,
 +                                             GeomAPI_DataMapOfShapeShape& theMapOfShapes)
 +{
 +  //load result
 +  if(theBaseShape->isEqual(theResultShape)) {
 +    theResultBody->store(theResultShape, false);
 +  } else {
 +    const int aModifyVTag = 1;
 +    const int aModifyETag = 2;
 +    const int aModifyFTag = 3;
 +    const int aDeletedTag = 4;
 +    /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids
 +    const int aSubsolidsTag = 5;
 +
 +    theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
 +
 +    const std::string aModVName = "Modified_Vertex";
 +    const std::string aModEName = "Modified_Edge";
 +    const std::string aModFName = "Modified_Face";
 +
 +    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX,
 +                                               aModifyVTag, aModVName, theMapOfShapes, false,
 +                                               true, true);
 +    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE,
 +                                               aModifyETag, aModEName, theMapOfShapes, false,
 +                                               true, true);
 +    theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
 +                                               aModifyFTag, aModFName, theMapOfShapes, false,
 +                                               true, true);
 +
 +    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
 +                                     GeomAPI_Shape::VERTEX, aDeletedTag);
 +    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
 +                                     GeomAPI_Shape::EDGE, aDeletedTag);
 +    theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape,
 +                                     GeomAPI_Shape::FACE, aDeletedTag);
 +
 +    for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++)
 +    {
 +      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX,
 +                                                 aModifyVTag, aModVName, theMapOfShapes, false,
 +                                                 true, true);
 +
 +      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE,
 +                                                 aModifyETag, aModEName, theMapOfShapes, false,
 +                                                 true, true);
 +
 +      theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE,
 +                                                 aModifyFTag, aModFName, theMapOfShapes, false,
 +                                                 true, true);
 +
 +      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, aDeletedTag);
 +      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, aDeletedTag);
 +      theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
 +    }
 +  }
 +}
index a57403e1af8b1cbd417f8fd6cb6e88edb6d9c6c8,0000000000000000000000000000000000000000..b3cc312c52097f8113056fb743f35972132a157e
mode 100644,000000..100644
--- /dev/null
@@@ -1,96 -1,0 +1,95 @@@
- #include <ModelAPI_ResultCompSolid.h>
 +// 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>
 +//
 +
 +#include "FeaturesPlugin_FusionFaces.h"
 +
 +#include <ModelAPI_AttributeSelectionList.h>
 +#include <ModelAPI_AttributeString.h>
 +#include <ModelAPI_ResultBody.h>
 +#include <ModelAPI_ResultConstruction.h>
 +#include <ModelAPI_Session.h>
 +#include <ModelAPI_Validator.h>
 +
 +#include <GeomAPI_ShapeIterator.h>
 +#include <GeomAPI_ShapeExplorer.h>
 +
 +#include <GeomAlgoAPI_UnifySameDomain.h>
 +
 +
 +//==================================================================================================
 +FeaturesPlugin_FusionFaces::FeaturesPlugin_FusionFaces()
 +{
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_FusionFaces::initAttributes()
 +{
 +  data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
 +}
 +
 +//==================================================================================================
 +void FeaturesPlugin_FusionFaces::execute()
 +{
 +  // Get selection.
 +  AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
 +  if (!aShapeAttrSelection.get()) {
 +    return;
 +  }
 +
 +  // Get shape.
 +  GeomShapePtr aBaseShape = aShapeAttrSelection->value();
 +
 +  // Make fusion
 +  std::shared_ptr<GeomAlgoAPI_UnifySameDomain> anAlgo(new GeomAlgoAPI_UnifySameDomain(aBaseShape));
 +
 +  // Check algo status
 +  if (!anAlgo->isDone()) {
 +    setError("Error: Fusion algorithm failed.");
 +    return;
 +  }
 +  if (anAlgo->shape()->isNull()) {
 +    setError("Error: Resulting shape is Null.");
 +    return;
 +  }
 +  if (!anAlgo->isValid()) {
 +    setError("Error: Resulting shape is not valid.");
 +    return;
 +  }
 +
 +  // Store result
 +  GeomShapePtr aResultShape = anAlgo->shape();
 +  ResultBodyPtr aResultBody = document()->createBody(data());
 +  if (aResultShape->isEqual(aBaseShape)) {
 +    aResultBody->store(aResultShape);
 +  } else {
 +    aResultBody->storeModified(aBaseShape, aResultShape);
 +
 +    const int aModifyEdgeTag = 1;
 +    const int aModifyFaceTag = 2;
 +    const std::string aModEName = "Modified_Edge";
 +    const std::string aModFName = "Modified_Face";
 +    std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfShapes = anAlgo->mapOfSubShapes();
 +    aResultBody->loadAndOrientModifiedShapes(anAlgo.get(), aBaseShape, GeomAPI_Shape::EDGE,
 +      aModifyEdgeTag, aModEName, *aMapOfShapes.get(), true);
 +    aResultBody->loadAndOrientModifiedShapes(anAlgo.get(), aBaseShape, GeomAPI_Shape::FACE,
 +      aModifyFaceTag, aModFName, *aMapOfShapes.get(), true);
 +  }
 +  setResult(aResultBody);
 +}
index 13b2c6cafd33f2918029f8456b368bc1ce55a020,605f9b919593425dbcb9138fba480a19e1b48ec4..4ab4e48cc1b151bcff7fe87fe58f2b25c0355846
@@@ -1156,343 -1167,3 +1170,343 @@@ bool FeaturesPlugin_ValidatorBooleanArg
  
    return false;
  }
-       ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
 +
 +//==================================================================================================
 +bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid(
 +  const AttributePtr& theAttribute,
 +  const std::list<std::string>& theArguments,
 +  Events_InfoMessage& theError) const
 +{
 +  std::shared_ptr<FeaturesPlugin_BooleanSmash> aFeature =
 +    std::dynamic_pointer_cast<FeaturesPlugin_BooleanSmash>(theAttribute->owner());
 +
 +  AttributeSelectionListPtr anAttrSelectionList =
 +    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
 +  if (!aFeature.get() || !anAttrSelectionList.get()) {
 +    theError =
 +      "Error: Validator used in wrong feature or attribute";
 +    return false;
 +  }
 +
 +  AttributeSelectionListPtr anOtherAttrSelectionList;
 +  if (theAttribute->id() == FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID()) {
 +    anOtherAttrSelectionList =
 +      aFeature->selectionList(FeaturesPlugin_BooleanSmash::TOOL_LIST_ID());
 +  } else {
 +    anOtherAttrSelectionList =
 +      aFeature->selectionList(FeaturesPlugin_BooleanSmash::OBJECT_LIST_ID());
 +  }
 +
 +  GeomAPI_Shape::ShapeType aSelectedShapesType = GeomAPI_Shape::SHAPE;
 +  GeomAPI_DataMapOfShapeShape aSelectedCompSolidsInOtherList;
 +  GeomPlanePtr aFacesPln;
 +
 +  for (int anIndex = 0; anIndex < anOtherAttrSelectionList->size(); ++anIndex) {
 +    AttributeSelectionPtr anAttrSelection = anOtherAttrSelectionList->value(anIndex);
 +    ResultPtr aContext = anAttrSelection->context();
 +    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
 +    GeomShapePtr aContextShape = aContext->shape();
 +    if (!aShape.get()) {
 +      aShape = aContextShape;
 +    }
 +
 +    if (aShape->isSolid() || aShape->isCompSolid()) {
 +      aSelectedShapesType = GeomAPI_Shape::SOLID;
-       ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
++      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +      if (aResCompSolidPtr.get()) {
 +        GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
 +        aSelectedCompSolidsInOtherList.bind(aCompSolidShape, aCompSolidShape);
 +      }
 +    } else {
 +      aSelectedShapesType = GeomAPI_Shape::FACE;
 +      GeomAPI_Face aFace(aShape);
 +      aFacesPln = aFace.getPlane();
 +      break;
 +    }
 +  }
 +
 +  for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
 +    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
 +    if (!anAttrSelection.get()) {
 +      theError = "Error: Empty attribute selection.";
 +      return false;
 +    }
 +    ResultPtr aContext = anAttrSelection->context();
 +    if (!aContext.get()) {
 +      theError = "Error: Empty selection context.";
 +      return false;
 +    }
 +    ResultConstructionPtr aResultConstruction =
 +      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
 +    if (aResultConstruction.get()) {
 +      theError = "Error: Result construction not allowed for selection.";
 +      return false;
 +    }
 +    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
 +    GeomShapePtr aContextShape = aContext->shape();
 +    if (!aShape.get()) {
 +      aShape = aContextShape;
 +    }
 +    if (!aShape.get()) {
 +      theError = "Error: Empty shape.";
 +      return false;
 +    }
 +    if (!aShape->isEqual(aContextShape)) {
 +      theError = "Error: Local selection not allowed.";
 +      return false;
 +    }
 +
 +    if (aSelectedShapesType == GeomAPI_Shape::SHAPE) {
 +      // Other list is empty.
 +      if (aShape->isSolid() || aShape->isCompSolid()) {
 +        aSelectedShapesType = GeomAPI_Shape::SOLID;
 +      } else {
 +        aSelectedShapesType = GeomAPI_Shape::FACE;
 +        GeomAPI_Face aFace(aShape);
 +        aFacesPln = aFace.getPlane();
 +
 +        if (!aFacesPln.get()) {
 +          theError = "Error: Only planar faces allowed.";
 +          return false;
 +        }
 +      }
 +
 +      continue;
 +    } else if (aSelectedShapesType == GeomAPI_Shape::SOLID) {
 +      if (!aShape->isSolid() && !aShape->isCompSolid()) {
 +        theError = "Error: Selected shapes should have the same type.";
 +        return false;
 +      }
 +
-   ResultCompSolidPtr aCompSolid;
++      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +      if (aResCompSolidPtr.get()) {
 +        GeomShapePtr aCompSolidShape = aResCompSolidPtr->shape();
 +        if (aSelectedCompSolidsInOtherList.isBound(aCompSolidShape)) {
 +          theError = "Error: Solids from compsolid in other list not allowed.";
 +          return false;
 +        }
 +      }
 +    } else {
 +      GeomAPI_Face aFace(aShape);
 +      GeomPlanePtr aPln = aFace.getPlane();
 +
 +      if (!aPln.get()) {
 +        theError = "Error: Only planar faces allowed.";
 +        return false;
 +      }
 +
 +      if (!aFacesPln->isCoincident(aPln)) {
 +        theError = "Error: Only coincident faces allowed.";
 +        return false;
 +      }
 +    }
 +  }
 +
 +  return true;
 +}
 +
 +//==================================================================================================
 +bool FeaturesPlugin_IntersectionSelection::isValid(const AttributePtr& theAttribute,
 +                                                   const std::list<std::string>& theArguments,
 +                                                   Events_InfoMessage& theError) const
 +{
 +  if (!theAttribute.get()) {
 +    theError = "Error: empty selection.";
 +    return false;
 +  }
 +  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
 +  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;
 +    }
 +    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" ||
 +        aFeatureKind == "Plane" ||
 +        aFeatureKind == "Axis") {
 +      theError = "Error: %1 shape is not allowed for selection.";
 +      theError.arg(aFeatureKind);
 +      return false;
 +    }
 +    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
 +    GeomShapePtr aContextShape = aContext->shape();
 +    if (!aShape.get()) {
 +      aShape = aContextShape;
 +    }
 +    if (!aShape.get()) {
 +      theError = "Error: empty shape.";
 +      return false;
 +    }
 +    if (!aShape->isEqual(aContextShape)) {
 +      theError = "Error: Local selection not allowed.";
 +      return false;
 +    }
 +
 +    int aShapeType = aShape->shapeType();
 +    // 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;
 +    }
 +  }
 +
 +  return true;
 +}
 +
 +//==================================================================================================
 +bool FeaturesPlugin_ValidatorBooleanFuseSelection::isValid(
 +  const AttributePtr& theAttribute,
 +  const std::list<std::string>& theArguments,
 +  Events_InfoMessage& theError) const
 +{
 +  AttributeSelectionListPtr anAttrSelectionList =
 +    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
 +  if (!anAttrSelectionList.get()) {
 +    theError =
 +      "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
 +    return false;
 +  }
 +
 +  for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
 +    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
 +    if (!anAttrSelection.get()) {
 +      theError = "Error: Empty attribute selection.";
 +      return false;
 +    }
 +    ResultPtr aContext = anAttrSelection->context();
 +    if (!aContext.get()) {
 +      theError = "Error: Empty selection context.";
 +      return false;
 +    }
 +    ResultConstructionPtr aResultConstruction =
 +      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
 +    if (aResultConstruction.get()) {
 +      theError = "Error: Result construction not allowed for selection.";
 +      return false;
 +    }
 +    std::shared_ptr<GeomAPI_Shape> aShape = anAttrSelection->value();
 +    GeomShapePtr aContextShape = aContext->shape();
 +    if (!aShape.get()) {
 +      aShape = aContextShape;
 +    }
 +    if (!aShape.get()) {
 +      theError = "Error: Empty shape.";
 +      return false;
 +    }
 +    if (!aShape->isEqual(aContextShape)) {
 +      theError = "Error: Local selection not allowed.";
 +      return false;
 +    }
 +  }
 +
 +  return true;
 +}
 +
 +//=================================================================================================
 +bool FeaturesPlugin_ValidatorBooleanFuseArguments::isValid(
 +  const std::shared_ptr<ModelAPI_Feature>& theFeature,
 +  const std::list<std::string>& theArguments,
 +  Events_InfoMessage& theError) const
 +{
 +  if (theArguments.size() != 2) {
 +    theError = "Wrong number of arguments (expected 2).";
 +    return false;
 +  }
 +
 +  std::shared_ptr<FeaturesPlugin_BooleanFuse> aFeature =
 +    std::dynamic_pointer_cast<FeaturesPlugin_BooleanFuse>(theFeature);
 +
 +  int anObjectsNb = 0, aToolsNb = 0;
 +
 +  std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
 +
 +  bool isAllInSameCompSolid = true;
-       ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
++  ResultBodyPtr aCompSolid;
 +
 +  AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(*anIt);
 +  if (anAttrSelList) {
 +    anObjectsNb = anAttrSelList->size();
 +    for (int anIndex = 0; anIndex < anObjectsNb; ++anIndex) {
 +      AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
 +      ResultPtr aContext = anAttr->context();
-           ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
++      ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +      if (aResCompSolidPtr.get()) {
 +        if (aCompSolid.get()) {
 +          isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
 +        } else {
 +          aCompSolid = aResCompSolidPtr;
 +        }
 +      } else {
 +        isAllInSameCompSolid = false;
 +        break;
 +      }
 +    }
 +  }
 +  anIt++;
 +
 +  if (aFeature->string(FeaturesPlugin_BooleanFuse::CREATION_METHOD())->value()
 +      == FeaturesPlugin_BooleanFuse::CREATION_METHOD_ADVANCED()) {
 +    anAttrSelList = theFeature->selectionList(*anIt);
 +    if (anAttrSelList) {
 +      aToolsNb = anAttrSelList->size();
 +      if (isAllInSameCompSolid) {
 +        for (int anIndex = 0; anIndex < aToolsNb; ++anIndex) {
 +          AttributeSelectionPtr anAttr = anAttrSelList->value(anIndex);
 +          ResultPtr aContext = anAttr->context();
++          ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext);
 +          if (aResCompSolidPtr.get()) {
 +            if (aCompSolid.get()) {
 +              isAllInSameCompSolid = aCompSolid == aResCompSolidPtr;
 +            } else {
 +              aCompSolid = aResCompSolidPtr;
 +            }
 +          } else {
 +            isAllInSameCompSolid = false;
 +            break;
 +          }
 +        }
 +      }
 +    }
 +  }
 +
 +  anIt++;
 +
 +  if (anObjectsNb + aToolsNb < 2) {
 +    theError = "Not enough arguments for Fuse operation.";
 +    return false;
 +  } else if (isAllInSameCompSolid) {
 +    theError = "Operations only between sub-shapes of the same shape not allowed.";
 +    return false;
 +  }
 +
 +  return true;
 +}
 +
 +//=================================================================================================
 +bool FeaturesPlugin_ValidatorBooleanFuseArguments::isNotObligatory(
 +  std::string theFeature,
 +  std::string theAttribute)
 +{
 +  if (theAttribute == "main_objects" || theAttribute == "tool_objects") {
 +    return true;
 +  }
 +
 +  return false;
 +}
index 23dfe5c972f538ebd349f20f4c97d0150a58b743,44d44c76003a41cd31856dd22bd2b4426215a2d6..d529c4cc50812ad31f5b53f783e7321ef484cc84
@@@ -133,10 -133,8 +133,9 @@@ aSession.undo(
  #=========================================================================
  aSession.startOperation()
  aBooleanFt = aPart.addFeature("Fuse")
- aBooleanFt.string("creation_method").setValue("advanced")
 -aBooleanFt.selectionList("main_objects").append(extrudedObjects[0].subResult(1), None)
 +aBooleanFt.selectionList("main_objects").append(modelAPI_ResultCompSolid(extrudedObjects[0]).subResult(1), None)
  aBooleanFt.selectionList("tool_objects").append(extrudedObjects[1], None)
 +aBooleanFt.boolean("remove_intersection_edges").setValue(False)
  aBooleanFt.execute()
  aSession.finishOperation()
  
index 5d71673a7de8f69e29714789cf05303a3257ba07,d42c54c57ebb8ee1f7634b9789bc62684a62261e..d441758f83bcda965ccb96a8a63cdf1d373fa1c8
@@@ -60,14 -60,7 +60,13 @@@ SET(PROJECT_HEADER
      GeomAPI_Ellipse.h
      GeomAPI_Ellipse2d.h
      GeomAPI_Tools.h
-     GeomAPI_IScreenParams.h
 -      GeomAPI_IScreenParams.h
 +    GeomAPI_Shell.h
 +    GeomAPI_Solid.h
 +    GeomAPI_Sphere.h
 +    GeomAPI_Cylinder.h
 +    GeomAPI_Cone.h
 +    GeomAPI_Torus.h
 +    GeomAPI_Box.h
  )
  
  SET(PROJECT_SOURCES