From: mpv Date: Thu, 16 Aug 2018 18:41:52 +0000 (+0300) Subject: Merge branch 'Results_Hierarchy' X-Git-Tag: SHAPER_V9_1_0RC1~73 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1e2eaa713f139d2617c80eba9ede62d4e9976bb7;p=modules%2Fshaper.git Merge branch 'Results_Hierarchy' --- 1e2eaa713f139d2617c80eba9ede62d4e9976bb7 diff --cc src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp index 1d7d14a5f,000000000..0319ee264 mode 100644,000000..100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp @@@ -1,374 -1,0 +1,374 @@@ +// 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 +// + +#include "FeaturesPlugin_BooleanFuse.h" + - #include ++#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//================================================================================================== +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, 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 anObject = anObjectAttr->value(); + if (!anObject.get()) { + return; + } + ResultPtr aContext = anObjectAttr->context(); - ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); ++ ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); + if (!isSimpleCreation + && aResCompSolidPtr.get() + && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { + std::shared_ptr aContextShape = aResCompSolidPtr->shape(); + std::map, 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, ListOfShape>::iterator + anIt = aCompSolidsObjects.begin(); + anIt != aCompSolidsObjects.end(); anIt++) { + std::shared_ptr 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 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 aCuttedEdgesAndFaces; + if (!anEdgesAndFaces.empty()) { + std::shared_ptr 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 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 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 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 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 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 aBackShape = anOriginalShapes.back(); + anOriginalShapes.pop_back(); + std::shared_ptr 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 theResultBody, + const std::shared_ptr theBaseShape, + const ListOfShape& theTools, + const std::shared_ptr 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); + } + } +} diff --cc src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp index ebc654958,000000000..f0aa745dd mode 100644,000000..100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanSmash.cpp @@@ -1,306 -1,0 +1,306 @@@ +// 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 +// + +#include "FeaturesPlugin_BooleanSmash.h" + - #include ++#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//================================================================================================== +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, 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 anObject = anObjectAttr->value(); + if(!anObject.get()) { + return; + } + ResultPtr aContext = anObjectAttr->context(); - ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); ++ ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); + if (aResCompSolidPtr.get()) + { + std::shared_ptr aContextShape = aResCompSolidPtr->shape(); + + std::map, 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, ListOfShape>::iterator + anIt = aCompSolidsObjects.begin(); + anIt != aCompSolidsObjects.end(); + ++anIt) + { + std::shared_ptr 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 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 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 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 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 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 aShape = aFillerAlgo->shape(); + aMakeShapeList.appendAlgo(aFillerAlgo); + aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); + + std::shared_ptr aFrontShape = anOriginalShapes.front(); + anOriginalShapes.pop_front(); + std::shared_ptr 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); + } + } +} diff --cc src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp index a57403e1a,000000000..b3cc312c5 mode 100644,000000..100644 --- a/src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_FusionFaces.cpp @@@ -1,96 -1,0 +1,95 @@@ +// 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 +// + +#include "FeaturesPlugin_FusionFaces.h" + +#include +#include +#include - #include +#include +#include +#include + +#include +#include + +#include + + +//================================================================================================== +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 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 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); +} diff --cc src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 13b2c6caf,605f9b919..4ab4e48cc --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@@ -1156,343 -1167,3 +1170,343 @@@ bool FeaturesPlugin_ValidatorBooleanArg return false; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorBooleanSmashSelection::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + std::shared_ptr aFeature = + std::dynamic_pointer_cast(theAttribute->owner()); + + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(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 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(aContext); + if (aResultConstruction.get()) { + theError = "Error: Result construction not allowed for selection."; + return false; + } + std::shared_ptr 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 aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); ++ 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& theArguments, + Events_InfoMessage& theError) const +{ + if (!theAttribute.get()) { + theError = "Error: empty selection."; + return false; + } + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(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 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& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr anAttrSelectionList = + std::dynamic_pointer_cast(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(aContext); + if (aResultConstruction.get()) { + theError = "Error: Result construction not allowed for selection."; + return false; + } + std::shared_ptr 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& theFeature, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + if (theArguments.size() != 2) { + theError = "Wrong number of arguments (expected 2)."; + return false; + } + + std::shared_ptr aFeature = + std::dynamic_pointer_cast(theFeature); + + int anObjectsNb = 0, aToolsNb = 0; + + std::list::const_iterator anIt = theArguments.begin(), aLast = theArguments.end(); + + bool isAllInSameCompSolid = true; - ResultCompSolidPtr aCompSolid; ++ 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(); - 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 (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; +} diff --cc src/FeaturesPlugin/Test/TestBooleanCompSolids.py index 23dfe5c97,44d44c760..d529c4cc5 --- a/src/FeaturesPlugin/Test/TestBooleanCompSolids.py +++ b/src/FeaturesPlugin/Test/TestBooleanCompSolids.py @@@ -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() diff --cc src/GeomAPI/CMakeLists.txt index 5d71673a7,d42c54c57..d441758f8 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@@ -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