From 03b823cbbe43236117bc50c34398f3ce273f729b Mon Sep 17 00:00:00 2001 From: dbv Date: Fri, 5 Feb 2016 17:52:34 +0300 Subject: [PATCH] 3. Mixed topology: solids, faces, edges and vertices Boolean Fuse operation now allow to fuse edges and faces with solids. --- src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp | 145 ++++++++++++------ src/FeaturesPlugin/boolean_widget.xml | 18 ++- src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp | 4 +- src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp | 27 ++-- src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp | 10 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 22 ++- src/GeomValidators/CMakeLists.txt | 3 +- .../GeomValidators_BooleanSelection.cpp | 75 +++++++++ .../GeomValidators_BooleanSelection.h | 31 ++++ src/GeomValidators/GeomValidators_Plugin.cpp | 2 + src/Model/Model_BodyBuilder.cpp | 5 +- src/Model/Model_ResultCompSolid.cpp | 12 +- 12 files changed, 272 insertions(+), 82 deletions(-) create mode 100644 src/GeomValidators/GeomValidators_BooleanSelection.cpp create mode 100644 src/GeomValidators/GeomValidators_BooleanSelection.h diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index ee767710c..25f8f3e0d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -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, 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, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); anIt != aCompSolidsObjects.end(); anIt++) { std::shared_ptr 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 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(!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 aCutAlgo(new GeomAlgoAPI_Boolean(aOneObjectList, aNotUsedSolids, GeomAlgoAPI_Boolean::BOOL_CUT)); + std::shared_ptr 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 aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, aTools, aType)); + 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, 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 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 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 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 aBackShape = anOriginalShapes.back(); + anOriginalShapes.pop_back(); std::shared_ptr 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 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); } } diff --git a/src/FeaturesPlugin/boolean_widget.xml b/src/FeaturesPlugin/boolean_widget.xml index ad8061acf..99d5ca699 100644 --- a/src/FeaturesPlugin/boolean_widget.xml +++ b/src/FeaturesPlugin/boolean_widget.xml @@ -14,19 +14,23 @@ label="Main objects" icon="" tooltip="Select solid objects" - type_choice="Solids" + type_choice="Solids Objects" + use_choice="false" concealment="true"> - + + - - + + diff --git a/src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp b/src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp index 166922710..a21ac5f04 100644 --- a/src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp +++ b/src/GeomAPI/GeomAPI_DataMapOfShapeShape.cpp @@ -44,7 +44,9 @@ void GeomAPI_DataMapOfShapeShape::merge(const GeomAPI_DataMapOfShapeShape& theDa void GeomAPI_DataMapOfShapeShape::merge(const std::shared_ptr theDataMap) { - merge(*theDataMap.get()); + if(theDataMap.get()) { + merge(*theDataMap.get()); + } } bool GeomAPI_DataMapOfShapeShape::isBound (std::shared_ptr theKey) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp index 5322a17e5..2fa01fadd 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp @@ -8,10 +8,7 @@ #include -#include -#include -#include -#include +#include #include //================================================================================================= @@ -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); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp index ad20d9edd..3dd1cb0b0 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_PaveFiller.cpp @@ -12,6 +12,7 @@ #include #include #include +#include //================================================================================================= 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()); + const TopoDS_Shape& aShape = (*anIt)->impl(); + 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(); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index de201f61c..852163df3 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -85,18 +85,28 @@ void GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr aTA = TopAbs_SOLID; } - // Map subshapes and shapes. + // Get free shapes. const TopoDS_Shape& aShapesComp = theCompound->impl(); - 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 aGeomShape(new GeomAPI_Shape); + aGeomShape->setImpl(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 aFreeShapes; NCollection_Vector> 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 aListOfShape.Clear(); for(NCollection_List::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; diff --git a/src/GeomValidators/CMakeLists.txt b/src/GeomValidators/CMakeLists.txt index aa2d4a021..ceb12b40d 100644 --- a/src/GeomValidators/CMakeLists.txt +++ b/src/GeomValidators/CMakeLists.txt @@ -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 index 000000000..f3f6f248d --- /dev/null +++ b/src/GeomValidators/GeomValidators_BooleanSelection.cpp @@ -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 +#include +#include + +bool GeomValidators_BooleanSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + if(!theAttribute.get()) { + theError = "Error: empty selection."; + return false; + } + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + int anOperationType = aFeature->integer("bool_type")->value(); + 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; + } + std::shared_ptr 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 index 000000000..59b5d3ce6 --- /dev/null +++ b/src/GeomValidators/GeomValidators_BooleanSelection.h @@ -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 + +#include +#include + +/// \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& theArguments, + std::string& theError) const; +}; + +#endif diff --git a/src/GeomValidators/GeomValidators_Plugin.cpp b/src/GeomValidators/GeomValidators_Plugin.cpp index 43d997084..497e0a70a 100644 --- a/src/GeomValidators/GeomValidators_Plugin.cpp +++ b/src/GeomValidators/GeomValidators_Plugin.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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); diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 9a8eaa643..1d3b8a4d5 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -225,8 +225,11 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr& 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 aDoc = std::dynamic_pointer_cast(document()); aDoc->addNamingName(aSubBuilder.NamedShape()->Label(), aSolidName); diff --git a/src/Model/Model_ResultCompSolid.cpp b/src/Model/Model_ResultCompSolid.cpp index 8f4523c45..87241ee29 100755 --- a/src/Model/Model_ResultCompSolid.cpp +++ b/src/Model/Model_ResultCompSolid.cpp @@ -171,10 +171,10 @@ void Model_ResultCompSolid::updateSubs(const std::shared_ptr& the bool aWasEmpty = mySubs.empty(); Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); unsigned int aSubIndex = 0; - TopExp_Explorer aSolids(aThisShape, TopAbs_SOLID); - for(; aSolids.More(); aSolids.Next(), aSubIndex++) { - std::shared_ptr aSolidShape(new GeomAPI_Shape); - aSolidShape->setImpl(new TopoDS_Shape(aSolids.Current())); + TopoDS_Iterator aShapesIter(aThisShape); + for(; aShapesIter.More(); aShapesIter.Next(), aSubIndex++) { + std::shared_ptr 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& 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); } -- 2.39.2