From 1fee4cd98a6745a530c05805c3741450054b7063 Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 7 Aug 2019 14:18:37 +0300 Subject: [PATCH] Task 2.5. Combination operations on Groups (issue #2935) Complete Group Addition operation --- .../CollectionPlugin_GroupAddition.cpp | 52 +++++++++++++++++-- .../CollectionPlugin_GroupAddition.h | 2 +- .../CollectionPlugin_Plugin.cpp | 2 + .../CollectionPlugin_Validators.cpp | 39 ++++++++++++++ .../CollectionPlugin_Validators.h | 26 +++++++--- .../group_addition_widget.xml | 2 +- src/Model/Model_ResultGroup.cpp | 47 ++++++++++++++++- src/Model/Model_ResultGroup.h | 5 ++ src/ModelAPI/ModelAPI_ResultGroup.h | 5 ++ src/PartSet/PartSet_IconFactory.cpp | 6 +-- 10 files changed, 168 insertions(+), 18 deletions(-) diff --git a/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp b/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp index 1c3795dc3..c27826ce8 100644 --- a/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp +++ b/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp @@ -26,20 +26,62 @@ #include #include +#include +#include + CollectionPlugin_GroupAddition::CollectionPlugin_GroupAddition() { } void CollectionPlugin_GroupAddition::initAttributes() { - data()->addAttribute(CollectionPlugin_Group::LIST_ID(), + data()->addAttribute(CollectionPlugin_GroupAddition::LIST_ID(), ModelAPI_AttributeSelectionList::typeId()); } -void CollectionPlugin_GroupAddition::execute() +static void explodeCompound(const GeomShapePtr& theCompound, ListOfShape& theSubs) +{ + if (theCompound->isCompound()) { + GeomAPI_ShapeIterator anIt(theCompound); + for (; anIt.more(); anIt.next()) + explodeCompound(anIt.current(), theSubs); + } + else + theSubs.push_back(theCompound); +} + +static void keepUniqueShapes(ListOfShape& theShapes) { - if (results().empty() || firstResult()->isDisabled()) { // just create result if not exists - ResultPtr aGroup = document()->createGroup(data()); - setResult(aGroup); + ListOfShape::iterator anIt = theShapes.begin(); + while (anIt != theShapes.end()) { + GeomShapePtr aCurrent = *anIt; + ListOfShape::iterator anIt2 = theShapes.begin(); + for (; anIt2 != anIt; ++anIt2) + if (aCurrent->isEqual(*anIt2)) + break; + if (anIt2 != anIt) { + // the same shape is found + ListOfShape::iterator aRemoveIt = anIt++; + theShapes.erase(aRemoveIt); + } + else + ++anIt; } } + +void CollectionPlugin_GroupAddition::execute() +{ + ResultGroupPtr aGroup = document()->createGroup(data()); + // clean the result of the operation + aGroup->store(GeomShapePtr()); + + // collect all unique sub-shapes + GeomShapePtr aCompound = aGroup->shape(); + ListOfShape aSubs; + explodeCompound(aCompound, aSubs); + keepUniqueShapes(aSubs); + aCompound = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs); + aGroup->store(aCompound); + + setResult(aGroup); +} diff --git a/src/CollectionPlugin/CollectionPlugin_GroupAddition.h b/src/CollectionPlugin/CollectionPlugin_GroupAddition.h index 4de080a6e..17b1ed1c6 100644 --- a/src/CollectionPlugin/CollectionPlugin_GroupAddition.h +++ b/src/CollectionPlugin/CollectionPlugin_GroupAddition.h @@ -46,7 +46,7 @@ class CollectionPlugin_GroupAddition : public CollectionPlugin_Group /// Returns the kind of a feature COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind() { - static std::string MY_KIND = CollectionPlugin_Group::ID(); + static std::string MY_KIND = CollectionPlugin_GroupAddition::ID(); return MY_KIND; } diff --git a/src/CollectionPlugin/CollectionPlugin_Plugin.cpp b/src/CollectionPlugin/CollectionPlugin_Plugin.cpp index e55620606..560615e5e 100644 --- a/src/CollectionPlugin/CollectionPlugin_Plugin.cpp +++ b/src/CollectionPlugin/CollectionPlugin_Plugin.cpp @@ -46,6 +46,8 @@ CollectionPlugin_Plugin::CollectionPlugin_Plugin() ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); aFactory->registerValidator("CollectionPlugin_FieldValidator", new CollectionPlugin_FieldValidator); + aFactory->registerValidator("CollectionPlugin_OperationAttribute", + new CollectionPlugin_GroupOperationAttributeValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/CollectionPlugin/CollectionPlugin_Validators.cpp b/src/CollectionPlugin/CollectionPlugin_Validators.cpp index d644c13f6..caf64d0bb 100644 --- a/src/CollectionPlugin/CollectionPlugin_Validators.cpp +++ b/src/CollectionPlugin/CollectionPlugin_Validators.cpp @@ -18,8 +18,10 @@ // #include "CollectionPlugin_Validators.h" +#include "CollectionPlugin_Group.h" #include "CollectionPlugin_Field.h" #include +#include #include @@ -42,3 +44,40 @@ bool CollectionPlugin_FieldValidator::isValid(const FeaturePtr& theFeature, theError = "Selection list is not initialized"; return false; } + +bool CollectionPlugin_GroupOperationAttributeValidator::isValid( + const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionListPtr aSelList = + std::dynamic_pointer_cast(theAttribute); + if (!aSelList) { + theError = "Error: This validator can only work with selection list of attributes"; + return false; + } + + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + // check selected items + std::string aType; + for (int anIndex = 0; anIndex < aSelList->size(); ++anIndex) { + AttributeSelectionPtr aCurSelection = aSelList->value(anIndex); + // applicable the groups only + ResultPtr aGroupResult = aCurSelection->context(); + if (aGroupResult->groupName() != ModelAPI_ResultGroup::group()) { + theError = "Error: Groups can be selected only."; + return false; + } + // groups of same type can be selected only + FeaturePtr aGroupFeature = ModelAPI_Feature::feature(aGroupResult->data()->owner()); + std::string aGroupType = + aGroupFeature->selectionList(CollectionPlugin_Group::LIST_ID())->selectionType(); + if (aType.empty()) + aType = aGroupType; + else if (aType != aGroupType) { + theError = "Error: Groups should have same type"; + return false; + } + } + return true; +} diff --git a/src/CollectionPlugin/CollectionPlugin_Validators.h b/src/CollectionPlugin/CollectionPlugin_Validators.h index 5932e2c4f..4f5db68d3 100644 --- a/src/CollectionPlugin/CollectionPlugin_Validators.h +++ b/src/CollectionPlugin/CollectionPlugin_Validators.h @@ -21,14 +21,13 @@ #define CollectionPlugin_Validators_H #include "CollectionPlugin.h" +#include #include -/**\class SketchPlugin_SolverErrorValidator -* \ingroup Validators -* \brief Validator for the solver error. -* -* Simply checks that solver error attribute is empty. Returns the attribute value as an error. -*/ +/**\class CollectionPlugin_FieldValidator + * \ingroup Validators + * \brief Validator for the field. + */ class CollectionPlugin_FieldValidator : public ModelAPI_FeatureValidator { public: @@ -41,4 +40,19 @@ public: Events_InfoMessage& theError) const; }; +/**\class CollectionPlugin_GroupOperationAttributeValidator + * \ingroup Validators + * \brief Validator for the parameters of operation on groups. + */ +class CollectionPlugin_GroupOperationAttributeValidator : public ModelAPI_AttributeValidator +{ + //! 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, + Events_InfoMessage& theError) const; +}; + #endif \ No newline at end of file diff --git a/src/CollectionPlugin/group_addition_widget.xml b/src/CollectionPlugin/group_addition_widget.xml index 5eab220ac..510e6953c 100644 --- a/src/CollectionPlugin/group_addition_widget.xml +++ b/src/CollectionPlugin/group_addition_widget.xml @@ -6,6 +6,6 @@ - + \ No newline at end of file diff --git a/src/Model/Model_ResultGroup.cpp b/src/Model/Model_ResultGroup.cpp index 7a4c5cfaf..87d1620f6 100644 --- a/src/Model/Model_ResultGroup.cpp +++ b/src/Model/Model_ResultGroup.cpp @@ -18,12 +18,19 @@ // #include +#include #include #include #include +#include +#include +#include +#include +#include + Model_ResultGroup::Model_ResultGroup(std::shared_ptr theOwnerData) { myOwnerData = theOwnerData; @@ -40,7 +47,25 @@ void Model_ResultGroup::colorConfigInfo(std::string& theSection, std::string& th std::shared_ptr Model_ResultGroup::shape() { std::shared_ptr aResult; - if (myOwnerData) { + // obtain stored shape + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData && aData->isValid()) { + TDF_Label aShapeLab = aData->shapeLab(); + Handle(TDF_Reference) aRef; + if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) { + aShapeLab = aRef->Get(); + } + Handle(TNaming_NamedShape) aName; + if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { + TopoDS_Shape aShape = aName->Get(); + if (!aShape.IsNull()) { + aResult.reset(new GeomAPI_Shape); + aResult->setImpl(new TopoDS_Shape(aShape)); + } + } + } + // collect shapes selected in group + if (!aResult && myOwnerData) { AttributeSelectionListPtr aList = myOwnerData->selectionList("group_list"); if (aList) { std::list > aSubs; @@ -57,3 +82,23 @@ std::shared_ptr Model_ResultGroup::shape() } return aResult; } + +void Model_ResultGroup::store(const GeomShapePtr& theShape) +{ + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData) { + TDF_Label aShapeLab = aData->shapeLab(); + aShapeLab.ForgetAttribute(TDF_Reference::GetID()); + aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID()); + + if (!theShape) + return; // bad shape + TopoDS_Shape aShape = theShape->impl(); + if (aShape.IsNull()) + return; // null shape inside + + // store the new shape as primitive + TNaming_Builder aBuilder(aShapeLab); + aBuilder.Generated(aShape); + } +} diff --git a/src/Model/Model_ResultGroup.h b/src/Model/Model_ResultGroup.h index aa0c068dd..68e549d32 100644 --- a/src/Model/Model_ResultGroup.h +++ b/src/Model/Model_ResultGroup.h @@ -41,6 +41,11 @@ public: /// Returns the compound of selected entities MODEL_EXPORT virtual std::shared_ptr shape(); + /// \brief Stores the result of operation made on groups. + /// Cleans the storage if empty shape is given. + /// param[in] theShape shape to store. + MODEL_EXPORT virtual void store(const GeomShapePtr& theShape); + /// Removes the stored builders MODEL_EXPORT virtual ~Model_ResultGroup() {} diff --git a/src/ModelAPI/ModelAPI_ResultGroup.h b/src/ModelAPI/ModelAPI_ResultGroup.h index 8644fc1cf..040f2a05c 100644 --- a/src/ModelAPI/ModelAPI_ResultGroup.h +++ b/src/ModelAPI/ModelAPI_ResultGroup.h @@ -52,6 +52,11 @@ public: return RESULT_GROUP_COLOR; } + /// \brief Stores the result of operation made on groups. + /// Cleans the storage if empty shape is given. + /// param[in] theShape shape to store. + MODELAPI_EXPORT virtual void store(const GeomShapePtr& theShape) + {} }; //! Pointer on feature object diff --git a/src/PartSet/PartSet_IconFactory.cpp b/src/PartSet/PartSet_IconFactory.cpp index 2b8118487..abe6aa025 100644 --- a/src/PartSet/PartSet_IconFactory.cpp +++ b/src/PartSet/PartSet_IconFactory.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -35,8 +36,6 @@ #include #include -#include - QMap PartSet_IconFactory::myIcons; PartSet_IconFactory::PartSet_IconFactory(PartSet_Module* theModule) @@ -128,8 +127,7 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj) if(aShape.get()) { switch(aShape->shapeType()) { case GeomAPI_Shape::COMPOUND: { - FeaturePtr aFeature = ModelAPI_Feature::feature(theObj); - if (aFeature.get() && aFeature->getKind() == CollectionPlugin_Group::ID()) { + if (aResult->groupName() == ModelAPI_ResultGroup::group()) { switch (aShape->typeOfCompoundShapes()) { case GeomAPI_Shape::VERTEX: return QIcon(":icons/group_vertex.png"); -- 2.39.2