From 3f1a42a51c7de1911c75453ff7134593d7d2c6b1 Mon Sep 17 00:00:00 2001 From: dbv Date: Fri, 20 May 2016 16:26:27 +0300 Subject: [PATCH] Issue #1366: "Partition" feature now modified to "Generalized Partition" --- src/BuildPlugin/BuildPlugin_Validators.cpp | 2 +- .../FeaturesPlugin_CompositeSketch.cpp | 6 +- .../FeaturesPlugin_Partition.cpp | 251 +++++++----------- src/FeaturesPlugin/FeaturesPlugin_Partition.h | 40 +-- src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 6 +- .../FeaturesPlugin_Validators.cpp | 110 ++------ .../FeaturesPlugin_Validators.h | 28 +- src/FeaturesPlugin/boolean_widget.xml | 6 +- src/FeaturesPlugin/group_widget.xml | 2 +- src/FeaturesPlugin/partition_widget.xml | 28 +- src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp | 11 +- src/GeomAlgoAPI/GeomAlgoAPI_Partition.h | 2 + src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 166 +++++++++--- src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 50 ++-- .../GeomValidators_BodyShapes.cpp | 28 +- src/Model/Model_BodyBuilder.cpp | 11 +- 16 files changed, 353 insertions(+), 394 deletions(-) diff --git a/src/BuildPlugin/BuildPlugin_Validators.cpp b/src/BuildPlugin/BuildPlugin_Validators.cpp index cde7cf95b..4027ff1d8 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.cpp +++ b/src/BuildPlugin/BuildPlugin_Validators.cpp @@ -302,7 +302,7 @@ bool BuildPlugin_ValidatorSubShapesSelection::isValid(const AttributePtr& theAtt } // Check that shape inside wire or face. - if(!GeomAlgoAPI_ShapeTools::isSubShapeInShape(aShapeInList, aBaseShape)) { + if(!GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aShapeInList, aBaseShape)) { theError = "Selected shape is not inside base face."; return false; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index 1759b26b8..309a4bd9d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -238,10 +238,10 @@ bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(const std::shared_ptr theMakeShape, - const int theResultIndex) + const int theIndex) { // Create result body. - ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); + ResultBodyPtr aResultBody = document()->createBody(data(), theIndex); // Store generated shape. aResultBody->storeGenerated(theBaseShape, theMakeShape->shape()); @@ -250,7 +250,7 @@ void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape int aGenTag = 1; storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag); - setResult(aResultBody, theResultIndex); + setResult(aResultBody, theIndex); } //================================================================================================= diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index 74e68707e..7d5e2e90c 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include //================================================================================================= @@ -33,185 +35,132 @@ FeaturesPlugin_Partition::FeaturesPlugin_Partition() //================================================================================================= void FeaturesPlugin_Partition::initAttributes() { - AttributeSelectionListPtr aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - FeaturesPlugin_Partition::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - aSelection->setSelectionType("SOLID"); - - aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - FeaturesPlugin_Partition::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - aSelection->setSelectionType("SOLID"); - - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID()); - - data()->addAttribute(COMBINE_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); } //================================================================================================= void FeaturesPlugin_Partition::execute() { - ListOfShape anObjects, aTools, aToolsForNaming; + ListOfShape anObjects, aPlanes; // Getting objects. - AttributeSelectionListPtr anObjectsSelList = selectionList(FeaturesPlugin_Partition::OBJECT_LIST_ID()); - for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { - std::shared_ptr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); - if (!anObject.get()) { - return; + AttributeSelectionListPtr anObjectsSelList = selectionList(BASE_OBJECTS_ID()); + for(int anIndex = 0; anIndex < anObjectsSelList->size(); ++anIndex) { + AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anIndex); + GeomShapePtr anObject = anObjectAttr->value(); + if(!anObject.get()) { + // It could be a construction plane. + ResultPtr aContext = anObjectAttr->context(); + aPlanes.push_back(anObjectAttr->context()->shape()); + } else { + anObjects.push_back(anObject); } - anObjects.push_back(anObject); } - - GeomAlgoAPI_MakeShapeList aMakeShapeList; std::list > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0); - // Getting tools. - AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Partition::TOOL_LIST_ID()); - for (int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) { - std::shared_ptr aToolAttr = aToolsSelList->value(aToolsIndex); - std::shared_ptr aTool = aToolAttr->value(); - if(!aTool.get()) { - // it could be a construction plane - ResultPtr aContext = aToolAttr->context(); - if(aContext.get()) { - aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aContext->shape(), aBoundingPoints); - std::shared_ptr aMkShCustom(new GeomAlgoAPI_MakeShapeCustom); - aMkShCustom->addModified(aContext->shape(), aTool); - aMakeShapeList.appendAlgo(aMkShCustom); - aTools.push_back(aTool); - aToolsForNaming.push_back(aContext->shape()); - } - } else { - aTools.push_back(aTool); - aToolsForNaming.push_back(aTool); - } + // Resize planes. + ListOfShape aTools; + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); anIt != aPlanes.cend(); ++anIt) { + GeomShapePtr aPlane = *anIt; + GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); + std::shared_ptr aMkShCustom(new GeomAlgoAPI_MakeShapeCustom); + aMkShCustom->addModified(aPlane, aTool); + aMakeShapeList->appendAlgo(aMkShCustom); + aTools.push_back(aTool); } - // Getting combine flag. - bool isCombine = boolean(COMBINE_ID())->value(); + // Create single result. + std::shared_ptr aPartitionAlgo(new GeomAlgoAPI_Partition(anObjects, aTools)); - if(anObjects.empty()/* || aTools.empty()*/) { - std::string aFeatureError = "Error: Not enough objects for partition operation."; + // Checking that the algorithm worked properly. + if (!aPartitionAlgo->isDone()) { + static const std::string aFeatureError = "Error: Partition algorithm failed."; + setError(aFeatureError); + return; + } + if (aPartitionAlgo->shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + return; + } + if (!aPartitionAlgo->isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; setError(aFeatureError); return; } + aMakeShapeList->appendAlgo(aPartitionAlgo); + GeomShapePtr aResultShape = aPartitionAlgo->shape(); int aResultIndex = 0; - - if(isCombine) { - // Create single result. - //if(!aTools.empty()) { - // // This is a workaround for naming. Passing compound of objects as argument instead each object separately. - // std::shared_ptr aCompoud = GeomAlgoAPI_CompoundBuilder::compound(anObjects); - // anObjects.clear(); - // anObjects.push_back(aCompoud); - //} - std::shared_ptr aPartitionAlgo(new GeomAlgoAPI_Partition(anObjects, aTools)); - - // Checking that the algorithm worked properly. - if (!aPartitionAlgo->isDone()) { - static const std::string aFeatureError = "Error: Partition algorithm failed."; - setError(aFeatureError); - return; - } - if (aPartitionAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if (!aPartitionAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo->shape()) > 1.e-27) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - aMakeShapeList.appendAlgo(aPartitionAlgo); - GeomAPI_DataMapOfShapeShape& aMapOfShapes = *aPartitionAlgo->mapOfSubShapes().get(); - std::shared_ptr aBaseShape = anObjects.front(); - anObjects.pop_front(); - aToolsForNaming.insert(aToolsForNaming.end(), anObjects.begin(), anObjects.end()); - loadNamingDS(aResultBody, aBaseShape, aToolsForNaming, aPartitionAlgo->shape(), aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; + anObjects.insert(anObjects.end(), aPlanes.begin(), aPlanes.end()); + if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { + for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) { + storeResult(anObjects, anIt.current(), aMakeShapeList, aResultIndex); + ++aResultIndex; } } else { - // Create result for each object. - for (ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { - std::shared_ptr anObject = *anObjectsIt; - ListOfShape aListWithObject; aListWithObject.push_back(anObject); - std::shared_ptr aPartitionAlgo(new GeomAlgoAPI_Partition(aListWithObject, aTools)); - - // Checking that the algorithm worked properly. - if (!aPartitionAlgo->isDone()) { - static const std::string aFeatureError = "Error: Partition algorithm failed."; - setError(aFeatureError); - return; - } - if (aPartitionAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if (!aPartitionAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; - } - - if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo->shape()) > 1.e-27) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - GeomAlgoAPI_MakeShapeList aMakeShapeListCopy = aMakeShapeList; - aMakeShapeListCopy.appendAlgo(aPartitionAlgo); - GeomAPI_DataMapOfShapeShape aMapOfShapes = *aPartitionAlgo->mapOfSubShapes().get(); - loadNamingDS(aResultBody, anObject, aToolsForNaming, aPartitionAlgo->shape(), aMakeShapeListCopy, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; - } - } + storeResult(anObjects, aResultShape, aMakeShapeList, aResultIndex); + ++aResultIndex; } - // remove the rest results if there were produced in the previous pass + // Remove the rest results if there were produced in the previous pass. removeResults(aResultIndex); } //================================================================================================= -void FeaturesPlugin_Partition::loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes) +void FeaturesPlugin_Partition::storeResult(const ListOfShape& theObjects, + const GeomShapePtr theResultShape, + const std::shared_ptr theMakeShape, + const int theIndex) { - //load result - if(theBaseShape->isEqual(theResultShape)) { - theResultBody->store(theResultShape); - } else { - const int aDeletedTag = 1; - const int aSubsolidsTag = 2; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids - const int aModifyTag = 100000; - int aModifyToolsTag = 200000; - std::ostringstream aStream; - - theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); - - std::string aModName = "Modified"; - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, - aModifyTag, aModName, theMapOfShapes, true); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDeletedTag); - - int anIndex = 1; - for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { - aStream.str(std::string()); - aStream.clear(); - aStream << aModName << "_" << anIndex++; - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, - aModifyToolsTag, aStream.str(), theMapOfShapes, true); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag); - aModifyToolsTag += 10000; + // Find base. + GeomShapePtr aBaseShape; + for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { + GeomShapePtr anObjectShape = *anIt; + ListOfShape aModifiedShapes; + theMakeShape->modified(anObjectShape, aModifiedShapes); + for(ListOfShape::const_iterator aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) { + GeomShapePtr aModShape = *aModIt; + if(theResultShape->isSubShape(aModShape)) { + aBaseShape = anObjectShape; + break; + } + } + if(aBaseShape.get()) { + break; } } + + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theIndex); + + // Store modified shape. + if(aBaseShape->isEqual(theResultShape)) { + aResultBody->store(theResultShape); + return; + } + + const int aDelTag = 1; + const int aSubTag = 2; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids + int aModTag = aSubTag + 10000; + const std::string aModName = "Modified"; + + aResultBody->storeModified(aBaseShape, theResultShape, aSubTag); + + std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); + int anIndex = 1; + for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { + std::ostringstream aStream; + aStream << aModName << "_" << anIndex++; + aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::EDGE, + aModTag, aStream.str(), *aMapOfSubShapes.get(), true); + aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::FACE, + aModTag, aStream.str(), *aMapOfSubShapes.get(), true); + aResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::EDGE, aDelTag); + aResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::FACE, aDelTag); + aModTag += 10000; + } + + setResult(aResultBody, theIndex); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.h b/src/FeaturesPlugin/FeaturesPlugin_Partition.h index bd7d7a7c5..ea50c6e0a 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.h @@ -14,39 +14,26 @@ /// \class FeaturesPlugin_Partition /// \ingroup Plugins -/// \brief Feature for applying of Partition operations on Solids. Partition makes conjunctional +/// \brief Feature for applying of Partition operations on Shapes. Partition makes conjunctional /// faces of solids as shared. The result of partitions is a compsolid. -/// Main objects are solids, tool objects are solids or faces class FeaturesPlugin_Partition : public ModelAPI_Feature { public: - /// Extrusion kind + /// Feature kind. inline static const std::string& ID() { static const std::string MY_ID("Partition"); return MY_ID; } - /// attribute name of referenced object - inline static const std::string& OBJECT_LIST_ID() - { - static const std::string MY_OBJECT_LIST_ID("main_objects"); - return MY_OBJECT_LIST_ID; - } - /// attribute name of tool object - inline static const std::string& TOOL_LIST_ID() - { - static const std::string MY_TOOL_LIST_ID("tool_objects"); - return MY_TOOL_LIST_ID; - } - /// attribute name of combine flag - inline static const std::string& COMBINE_ID() + /// Attribute name of base objects. + inline static const std::string& BASE_OBJECTS_ID() { - static const std::string MY_COMBINE_ID("partition_combine"); - return MY_COMBINE_ID; + static const std::string MY_BASE_OBJECTS_ID("base_objects"); + return MY_BASE_OBJECTS_ID; } - /// Returns the kind of a feature + /// \return the kind of a feature. FEATURESPLUGIN_EXPORT virtual const std::string& getKind() { static std::string MY_KIND = FeaturesPlugin_Partition::ID(); @@ -63,14 +50,11 @@ public: FeaturesPlugin_Partition(); private: - /// Load Naming data structure of the feature to the document - void loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes); - + /// Stores result of generation. + void storeResult(const ListOfShape& theObjects, + const GeomShapePtr theResultShape, + const std::shared_ptr theMakeShape, + const int theIndex = 0); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 4bea20fc2..75ee7ff66 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -44,8 +44,10 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorPipeLocations); aFactory->registerValidator("FeaturesPlugin_ValidatorCanBeEmpty", new FeaturesPlugin_ValidatorCanBeEmpty); - aFactory->registerValidator("FeaturesPlugin_BooleanSelection", - new FeaturesPlugin_BooleanSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSelection", + new FeaturesPlugin_ValidatorBooleanSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection", + new FeaturesPlugin_ValidatorPartitionSelection); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 37d03e3a9..4f9d860c7 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -16,6 +16,7 @@ #include +#include #include #include @@ -377,93 +378,9 @@ bool FeaturesPlugin_ValidatorCanBeEmpty::isShapesCanBeEmpty(const AttributePtr& } //================================================================================================== -bool FeaturesPlugin_ValidatorBaseForWire::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - std::string& theError) const -{ - // Get base objects list. - if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { - Events_Error::send("Validator does not support attribute type \"" + theAttribute->attributeType() - + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + "\" supported."); - return false; - } - AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast(theAttribute); - if(!aSelectionList.get()) { - theError = "Could not get selection list."; - return false; - } - if(aSelectionList->size() == 0) { - theError = "Empty selection list."; - return false; - } - - // Collect base shapes. - ListOfShape aListOfShapes; - for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { - AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); - if(!aSelection.get()) { - theError = "Could not get selection."; - return false; - } - ResultPtr aContext = aSelection->context(); - if(!aContext.get()) { - theError = "Attribute have empty context."; - return false; - } - - GeomShapePtr aShape = aSelection->value(); - GeomShapePtr aContextShape = aContext->shape(); - if(!aShape.get()) { - aShape = aContextShape; - } - if(!aShape.get()) { - theError = "Empty shape selected."; - return false; - } - - // Check that shape has acceptable type. - if(aShape->shapeType() != GeomAPI_Shape::EDGE && aShape->shapeType() != GeomAPI_Shape::WIRE) { - theError = "Selected shape has wrong type. Only edges and wires acceptable."; - return false; - } - - // Check that it is edge on sketch. - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); - if(aConstruction.get()) { - if(aConstruction->isInfinite()) { - theError = "Inifinte objects not acceptable."; - return false; - } - - std::shared_ptr anEdges = std::dynamic_pointer_cast(aContextShape); - if(!anEdges.get()) { - // It is not an edge on the sketch. - // Check that it is not local selection. - if(!aShape->isEqual(aContextShape)) { - // Local selection on body does not allowed. - theError = "Selected shape is in the local selection. Only global selection is allowed."; - return false; - } - } - } - - aListOfShapes.push_back(aShape); - } - - // Create wire. - GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes); - if(!aWire.get()) { - theError = "Result wire empty. Probably it has disconnected edges or non-manifold."; - return false; - } - - return true; -} - -//================================================================================================== -bool FeaturesPlugin_BooleanSelection::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - std::string& theError) const +bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const { AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast(theAttribute); if(!anAttrSelectionList.get()) { @@ -521,3 +438,22 @@ bool FeaturesPlugin_BooleanSelection::isValid(const AttributePtr& theAttribute, return true; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + GeomValidators_BodyShapes aBodyValidator; + if(aBodyValidator.isValid(theAttribute, theArguments, theError)) { + return true; + } + + GeomValidators_FeatureKind aFeatureKindValidator; + if(aFeatureKindValidator.isValid(theAttribute, theArguments, theError)) { + return true; + } + + theError = "Only body shapes and construction planes are allowed for selection."; + return false; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 1b957a777..905eec5c6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -87,26 +87,26 @@ private: std::string& theError) const; }; -/// \class FeaturesPlugin_ValidatorBaseForWire +/// \class FeaturesPlugin_ValidatorBooleanSelection /// \ingroup Validators -/// \brief A validator for selection base shapes for wire. Allows to select edges on sketch and -/// wires objects that are connected to already selected shapes. -class FeaturesPlugin_ValidatorBaseForWire: public ModelAPI_AttributeValidator +/// \brief Validates selection for boolean operation. +class FeaturesPlugin_ValidatorBooleanSelection: public ModelAPI_AttributeValidator { public: - //! Returns true if attribute is ok. - //! \param[in] theAttribute the checked attribute. - //! \param[in] theArguments arguments of the attribute. - //! \param[out] theError error message. - virtual bool isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - std::string& theError) const; + /// \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. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; }; -/// \class FeaturesPlugin_BooleanSelection +/// \class FeaturesPlugin_ValidatorPartitionSelection /// \ingroup Validators -/// \brief Validates selection for boolean operation. -class FeaturesPlugin_BooleanSelection: public ModelAPI_AttributeValidator +/// \brief Validates selection for partition. +class FeaturesPlugin_ValidatorPartitionSelection: public ModelAPI_AttributeValidator { public: /// \return True if the attribute is valid. It checks whether the selection diff --git a/src/FeaturesPlugin/boolean_widget.xml b/src/FeaturesPlugin/boolean_widget.xml index 3d1a0ac58..5ccf5998b 100644 --- a/src/FeaturesPlugin/boolean_widget.xml +++ b/src/FeaturesPlugin/boolean_widget.xml @@ -4,7 +4,7 @@ - + - + diff --git a/src/FeaturesPlugin/group_widget.xml b/src/FeaturesPlugin/group_widget.xml index 731522c55..8567eb893 100644 --- a/src/FeaturesPlugin/group_widget.xml +++ b/src/FeaturesPlugin/group_widget.xml @@ -5,6 +5,6 @@ tooltip="Select a set of objects" type_choice="Vertices Edges Faces Solids" use_choice="true"> - + \ No newline at end of file diff --git a/src/FeaturesPlugin/partition_widget.xml b/src/FeaturesPlugin/partition_widget.xml index 0c770c318..ec2ea7105 100755 --- a/src/FeaturesPlugin/partition_widget.xml +++ b/src/FeaturesPlugin/partition_widget.xml @@ -1,28 +1,12 @@ - - - + - - - - - - + diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp index 7034f9d4c..06849b9f1 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Partition.cpp @@ -65,25 +65,16 @@ void GeomAlgoAPI_Partition::build(const ListOfShape& theObjects, } TopoDS_Shape aResult = anOperation->Shape(); - if(aResult.ShapeType() == TopAbs_COMPOUND) { - aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); - } if(aResult.ShapeType() == TopAbs_COMPOUND) { std::shared_ptr aGeomShape(new GeomAPI_Shape); aGeomShape->setImpl(new TopoDS_Shape(aResult)); - ListOfShape aCompSolids, aFreeSolids; - aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape, - GeomAPI_Shape::COMPSOLID, - aCompSolids, - aFreeSolids); - aResult = aGeomShape->impl(); + aResult = GeomAlgoAPI_ShapeTools::groupSharedTopology(aGeomShape)->impl(); } // Setting result. if(aResult.IsNull()) { return; } - aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(aResult)); this->setShape(aShape); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Partition.h b/src/GeomAlgoAPI/GeomAlgoAPI_Partition.h index ea214adde..5ab20e065 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Partition.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Partition.h @@ -21,6 +21,8 @@ public: /// \brief Creates common partition operation. /// \param[in] theObjects the main shape. /// \param[in] theTools second shape. + /// \param[in] theGroupConnectedTopology if true then result will be a compound of groups + /// with connected topology(compsolids or compounds of shapes with shared topology). /// \return a solid as result of operation. GEOMALGOAPI_EXPORT static std::shared_ptr make(const ListOfShape& theObjects, const ListOfShape& theTools); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 87e6d83c2..e6a89baa1 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -49,8 +49,9 @@ #include #include -//================================================================================================= -double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theShape) +namespace GeomAlgoAPI_ShapeTools { +//================================================================================================== +double volume(const std::shared_ptr theShape) { GProp_GProps aGProps; if(!theShape.get()) { @@ -65,8 +66,8 @@ double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr theSh return aGProps.Mass(); } -//================================================================================================= -std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(const std::shared_ptr theShape) +//================================================================================================== +std::shared_ptr centreOfMass(const std::shared_ptr theShape) { GProp_GProps aGProps; if(!theShape) { @@ -89,11 +90,11 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::centreOfMass(const std::sha return std::shared_ptr(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); } -//================================================================================================= -std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std::shared_ptr theCompound, - const GeomAPI_Shape::ShapeType theType, - ListOfShape& theCombinedShapes, - ListOfShape& theFreeShapes) +//================================================================================================== +std::shared_ptr combineShapes(const std::shared_ptr theCompound, + const GeomAPI_Shape::ShapeType theType, + ListOfShape& theCombinedShapes, + ListOfShape& theFreeShapes) { GeomShapePtr aResult = theCompound; @@ -112,6 +113,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std:: aTA = TopAbs_SOLID; } + theCombinedShapes.clear(); + theFreeShapes.clear(); + // Get free shapes. const TopoDS_Shape& aShapesComp = theCompound->impl(); for(TopoDS_Iterator anIter(aShapesComp); anIter.More(); anIter.Next() ) { @@ -234,8 +238,107 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::combineShapes(const std:: return aResult; } -//================================================================================================= -std::list > GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge) +//================================================================================================== +static void addSimpleShapeToList(const TopoDS_Shape& theShape, NCollection_List& theList) +{ + if(theShape.IsNull()) { + return; + } + + if(theShape.ShapeType() == TopAbs_COMPOUND) { + for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) { + addSimpleShapeToList(anIt.Value(), theList); + } + } else { + theList.Append(theShape); + } +} + +//================================================================================================== +static TopoDS_Compound makeCompound(const NCollection_List theShapes) +{ + TopoDS_Compound aCompound; + + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + + for(NCollection_List::Iterator anIt(theShapes); anIt.More(); anIt.Next()) { + aBuilder.Add(aCompound, anIt.Value()); + } + + return aCompound; +} + +//================================================================================================== +std::shared_ptr groupSharedTopology(const std::shared_ptr theCompound) +{ + GeomShapePtr aResult = theCompound; + + if(!theCompound.get()) { + return aResult; + } + + TopoDS_Shape anInShape = aResult->impl(); + NCollection_List anUngroupedShapes; + addSimpleShapeToList(anInShape, anUngroupedShapes); + + NCollection_Vector> aGroups; + while(!anUngroupedShapes.IsEmpty()) { + NCollection_List aGroupedShapes; + aGroupedShapes.Append(anUngroupedShapes.First()); + anUngroupedShapes.RemoveFirst(); + for(NCollection_List::Iterator aGroupIt(aGroupedShapes); aGroupIt.More(); aGroupIt.Next()) { + const TopoDS_Shape& aGroupShape = aGroupIt.Value(); + for(NCollection_List::Iterator anUngroupedIt(anUngroupedShapes); anUngroupedIt.More(); anUngroupedIt.Next()) { + const TopoDS_Shape& anUngroupedShape = anUngroupedIt.Value(); + bool isFound = false; + for(TopExp_Explorer aGroupShapeExp(aGroupShape, TopAbs_VERTEX); aGroupShapeExp.More(); aGroupShapeExp.Next()) { + const TopoDS_Shape& aVertex1 = aGroupShapeExp.Current(); + for(TopExp_Explorer anUngroupedShapeExp(anUngroupedShape, TopAbs_VERTEX); anUngroupedShapeExp.More(); anUngroupedShapeExp.Next()) { + const TopoDS_Shape& aVertex2 = anUngroupedShapeExp.Current(); + if(aVertex1.IsSame(aVertex2)) { + aGroupedShapes.Append(anUngroupedShape); + anUngroupedShapes.Remove(anUngroupedIt); + isFound = true; + break; + } + } + if(isFound) { + break; + } + } + if(!anUngroupedIt.More()) { + break; + } + } + } + aGroups.Append(aGroupedShapes); + } + + TopoDS_Compound aCompound; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aCompound); + ListOfShape aCompSolids, aFreeSolids; + for(NCollection_Vector>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) { + TopoDS_Compound aGroupCompound = makeCompound(anIt.Value()); + GeomShapePtr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(aGroupCompound)); + aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape, + GeomAPI_Shape::COMPSOLID, + aCompSolids, + aFreeSolids); + aBuilder.Add(aCompound, aGeomShape->impl()); + } + + if(!aCompound.IsNull()) { + aResult->setImpl(new TopoDS_Shape(aCompound)); + } + + return aResult; +} + +//================================================================================================== +std::list > getBoundingBox(const ListOfShape& theShapes, const double theEnlarge) { // Bounding box of all objects. Bnd_Box aBndBox; @@ -268,8 +371,8 @@ std::list > GeomAlgoAPI_ShapeTools::getBoundingBox( return aResultPoints; } -//================================================================================================= -std::shared_ptr GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const std::shared_ptr theFace) +//================================================================================================== +std::shared_ptr faceToInfinitePlane(const std::shared_ptr theFace) { if (!theFace.get()) return std::shared_ptr(); @@ -290,9 +393,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::faceToInfinitePlane(const return aResult; } -//================================================================================================= -std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std::shared_ptr thePlane, - const std::list >& thePoints) +//================================================================================================== +std::shared_ptr fitPlaneToBox(const std::shared_ptr thePlane, + const std::list >& thePoints) { std::shared_ptr aResultShape; @@ -343,10 +446,10 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std:: return aResultShape; } -//================================================================================================= -void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr theShape, - std::shared_ptr& theV1, - std::shared_ptr& theV2) +//================================================================================================== +void findBounds(const std::shared_ptr theShape, + std::shared_ptr& theV1, + std::shared_ptr& theV2) { if(!theShape.get()) { std::shared_ptr aVertex(new GeomAPI_Vertex); @@ -367,14 +470,14 @@ void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr the theV2 = aGeomV2; } -//================================================================================================= -void GeomAlgoAPI_ShapeTools::makeFacesWithHoles(const std::shared_ptr theOrigin, - const std::shared_ptr theDirection, - const ListOfShape& theWires, - ListOfShape& theFaces) +//================================================================================================== +void makeFacesWithHoles(const std::shared_ptr theOrigin, + const std::shared_ptr theDirection, + const ListOfShape& theWires, + ListOfShape& theFaces) { BRepBuilderAPI_MakeFace aMKFace(gp_Pln(theOrigin->impl(), - theDirection->impl())); + theDirection->impl())); TopoDS_Face aFace = aMKFace.Face(); BRepAlgo_FaceRestrictor aFRestrictor; @@ -399,8 +502,8 @@ void GeomAlgoAPI_ShapeTools::makeFacesWithHoles(const std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape& theShapes) +//================================================================================================== +std::shared_ptr findPlane(const ListOfShape& theShapes) { TopoDS_Compound aCompound; BRep_Builder aBuilder; @@ -427,9 +530,9 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape return aPln; } -//================================================================================================= -bool GeomAlgoAPI_ShapeTools::isSubShapeInShape(const std::shared_ptr theSubShape, - const std::shared_ptr theBaseShape) +//================================================================================================== +bool isSubShapeInsideShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape) { if(!theSubShape.get() || !theBaseShape.get()) { return false; @@ -497,3 +600,4 @@ bool GeomAlgoAPI_ShapeTools::isSubShapeInShape(const std::shared_ptr theShape); + GEOMALGOAPI_EXPORT double volume(const std::shared_ptr theShape); /// \return the centre of mass of the current face. The coordinates returned for the center of mass /// are expressed in the absolute Cartesian coordinate system. (This function works only for surfaces). - static std::shared_ptr centreOfMass(const std::shared_ptr theShape); + GEOMALGOAPI_EXPORT std::shared_ptr centreOfMass(const std::shared_ptr theShape); /// \brief Combines faces with common edges to shells, or solids to compsolids. /// \param[in] theCompound compound of shapes. /// \param[in] theType type of combine. /// \param[out] theCombinedShapes resulting shapes. /// \param[out] theFreeShapes shapes that does not have common subshapes. - static std::shared_ptr combineShapes(const std::shared_ptr theCompound, - const GeomAPI_Shape::ShapeType theType, - ListOfShape& theCombinedShapes, - ListOfShape& theFreeShapes); + GEOMALGOAPI_EXPORT std::shared_ptr combineShapes(const std::shared_ptr theCompound, + const GeomAPI_Shape::ShapeType theType, + ListOfShape& theCombinedShapes, + ListOfShape& theFreeShapes); + + /// \brief Groups shapes with shared topology to compounds. + /// \param[in] theCompound compound of shapes. + /// \return compound of compounds with shared topology. + GEOMALGOAPI_EXPORT std::shared_ptr groupSharedTopology(const std::shared_ptr theCompound); /// \brief Calculates bounding box for theShapes /// \return list of eight points. /// \param[in] theShapes list of shapes. /// \param[in] theEnlarge enlarges bounding box size. - static std::list > getBoundingBox(const ListOfShape& theShapes, const double theEnlarge = 0.0); + GEOMALGOAPI_EXPORT std::list > getBoundingBox(const ListOfShape& theShapes, const double theEnlarge = 0.0); /// \return infinite plane received from theFace plane. - static std::shared_ptr faceToInfinitePlane(const std::shared_ptr theFace); + GEOMALGOAPI_EXPORT std::shared_ptr faceToInfinitePlane(const std::shared_ptr theFace); /// \brief Enlarges or reduces plane to fit bounding box. /// \return plane that fits to bounding box. /// \param[in] thePlane base plane. /// \param[in] thePoints bounding box points (shoud be eight). - static std::shared_ptr fitPlaneToBox(const std::shared_ptr thePlane, - const std::list >& thePoints); + GEOMALGOAPI_EXPORT std::shared_ptr fitPlaneToBox(const std::shared_ptr thePlane, + const std::list >& thePoints); /// \brief Finds the start and end vertices of theShape. theShape can be of the following type:\n /// Vertex: theV1 and theV2 are the same and equal to theShape;\n @@ -62,29 +66,29 @@ public: /// Wire : theV1 is start vertex of the first edge, theV2 is end vertex of the last edge. If wire /// contains no edges theV1 and theV2 are nullified.\n /// If none of the above theV1 and theV2 are nullified. - static void findBounds(const std::shared_ptr theShape, - std::shared_ptr& theV1, - std::shared_ptr& theV2); + GEOMALGOAPI_EXPORT void findBounds(const std::shared_ptr theShape, + std::shared_ptr& theV1, + std::shared_ptr& theV2); /// \brief Creates faces with holes from wires. /// \param[in] theWires base wires. /// \param[out] theFaces resulting faces. - static void makeFacesWithHoles(const std::shared_ptr theOrigin, - const std::shared_ptr theDirection, - const ListOfShape& theWires, - ListOfShape& theFaces); + GEOMALGOAPI_EXPORT void makeFacesWithHoles(const std::shared_ptr theOrigin, + const std::shared_ptr theDirection, + const ListOfShape& theWires, + ListOfShape& theFaces); /// \brief Return a plane for list of shapes if they are all planar. /// \param[in] theShapes shapes to find plane. /// \return plane where all shapes lie or empty ptr if they not planar. - static std::shared_ptr findPlane(const ListOfShape& theShapes); + GEOMALGOAPI_EXPORT std::shared_ptr findPlane(const ListOfShape& theShapes); /// \brief Checks that vertex/edge is inside face or vertext inside wire. /// \param[in] theSubShape shape that should be inside. /// \param[in] theBaseShape base shape. /// \return true if edge inside the face. - static bool isSubShapeInShape(const std::shared_ptr theSubShape, - const std::shared_ptr theBaseShape); + GEOMALGOAPI_EXPORT bool isSubShapeInsideShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape); }; #endif diff --git a/src/GeomValidators/GeomValidators_BodyShapes.cpp b/src/GeomValidators/GeomValidators_BodyShapes.cpp index 734938ecc..13e95ace0 100644 --- a/src/GeomValidators/GeomValidators_BodyShapes.cpp +++ b/src/GeomValidators/GeomValidators_BodyShapes.cpp @@ -8,27 +8,29 @@ #include #include +#include bool GeomValidators_BodyShapes::isValid(const AttributePtr& theAttribute, - const std::list& theArguments, - std::string& theError) const + const std::list& theArguments, + std::string& theError) const { std::string anAttributeType = theAttribute->attributeType(); - if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { AttributeSelectionListPtr aSelectionListAttr = std::dynamic_pointer_cast(theAttribute); // all context objects should not be sketch entities - for(int i = 0, aSize = aSelectionListAttr->size(); i < aSize; i++) { - AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i); - ObjectPtr anObject = aSelectAttr->context(); - if (!anObject.get()) + for(int anIndex = 0, aSize = aSelectionListAttr->size(); anIndex < aSize; ++anIndex) { + AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex); + ResultPtr aContext = aSelectAttr->context(); + if(!aContext.get()) { + theError = "Error: Context is empty."; + return false; + } + + ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast(aContext); + if(aResultConstruction.get()) { + theError = "Error: Result construction selected."; return false; - else { - FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); - std::string aFeatureKind = aFeature->getKind(); - if(aFeatureKind == "Sketch") { - return false; - } } } } diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 2d025aa88..fe1541286 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -370,13 +370,14 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( GeomAPI_DataMapOfShapeShape& theSubShapes, const bool theIsStoreSeparate) { + int anIndex = 1; int aTag = theTag; + bool isBuilt = !theName.empty(); std::string aName = theName; std::ostringstream aStream; - int anIndex = 1; + GeomShapePtr aResultShape = shape(); TopoDS_Shape aShapeIn = theShapeIn->impl(); TopTools_MapOfShape aView; - bool isBuilt = theName.empty(); TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { const TopoDS_Shape& aRoot = aShapeExplorer.Current (); @@ -387,14 +388,14 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( theMS->modified(aRShape, aList); std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); + TopoDS_Shape aNewShape = (*anIt)->impl(); if (theSubShapes.isBound(*anIt)) { std::shared_ptr aMapShape(theSubShapes.find(*anIt)); aNewShape.Orientation(aMapShape->impl().Orientation()); } - if (!aRoot.IsSame (aNewShape)) { + if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(*anIt)) { builder(aTag)->Modify(aRoot,aNewShape); - if(!isBuilt) { + if(isBuilt) { if(theIsStoreSeparate) { aStream.str(std::string()); aStream.clear(); -- 2.39.2