Salome HOME
Task 2.5. Combination operations on Groups (issue #2935)
authorazv <azv@opencascade.com>
Wed, 7 Aug 2019 11:18:37 +0000 (14:18 +0300)
committerazv <azv@opencascade.com>
Wed, 7 Aug 2019 11:18:37 +0000 (14:18 +0300)
Complete Group Addition operation

src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp
src/CollectionPlugin/CollectionPlugin_GroupAddition.h
src/CollectionPlugin/CollectionPlugin_Plugin.cpp
src/CollectionPlugin/CollectionPlugin_Validators.cpp
src/CollectionPlugin/CollectionPlugin_Validators.h
src/CollectionPlugin/group_addition_widget.xml
src/Model/Model_ResultGroup.cpp
src/Model/Model_ResultGroup.h
src/ModelAPI/ModelAPI_ResultGroup.h
src/PartSet/PartSet_IconFactory.cpp

index 1c3795dc3799d401c9b410635a8cae13ae62b6d0..c27826ce850af6f1e8bdd791ae540b7a57b10ecf 100644 (file)
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_ResultGroup.h>
 
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
 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);
+}
index 4de080a6e90d89293ec4c2e94101a83a09e65520..17b1ed1c655d6761871cae24663020f0faa5a3b6 100644 (file)
@@ -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;
   }
 
index e5562060668ffb3efec5cb18dda3ed8d3bc2f3e2..560615e5ecccbb1ae81830b50b5ceb1a8bb8ed17 100644 (file)
@@ -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);
index d644c13f64817c4bc9f0da5fa700e3ddaea72fe1..caf64d0bbed7a6f8e264de786e131d5355a1f4a2 100644 (file)
 //
 
 #include "CollectionPlugin_Validators.h"
+#include "CollectionPlugin_Group.h"
 #include "CollectionPlugin_Field.h"
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
 #include <Events_InfoMessage.h>
 
 
@@ -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<std::string>& theArguments,
+    Events_InfoMessage& theError) const
+{
+  AttributeSelectionListPtr aSelList =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(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;
+}
index 5932e2c4f7d163e8228d2a2407ab00261656bcd5..4f5db68d31cfcc7a14e6fde63f8108cc9d650941 100644 (file)
 #define CollectionPlugin_Validators_H
 
 #include "CollectionPlugin.h"
+#include <ModelAPI_AttributeValidator.h>
 #include <ModelAPI_FeatureValidator.h>
 
-/**\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<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
 #endif
\ No newline at end of file
index 5eab220ac9a80387f1715faa38c701bec63196cb..510e6953cc485dd292215c9f5c5b319d215a4a94 100644 (file)
@@ -6,6 +6,6 @@
   <multi_selector id="group_list"
                   tooltip="Select a set of groups"
                   type_choice="objects">
-<!--    <validator id="GeomValidators_BodyShapes"/>-->
+    <validator id="CollectionPlugin_OperationAttribute"/>
   </multi_selector>
 </source>
\ No newline at end of file
index 7a4c5cfaf740f12e177ec415a201f3c356e1ab05..87d1620f6b3644f3525ac35273734dda34f595b8 100644 (file)
 //
 
 #include <Model_ResultGroup.h>
+#include <Model_Data.h>
 #include <ModelAPI_AttributeSelectionList.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
 
 #include <Config_PropManager.h>
 
+#include <TDF_Label.hxx>
+#include <TDF_Reference.hxx>
+#include <TNaming_Builder.hxx>
+#include <TNaming_NamedShape.hxx>
+#include <TopoDS_Shape.hxx>
+
 Model_ResultGroup::Model_ResultGroup(std::shared_ptr<ModelAPI_Data> theOwnerData)
 {
   myOwnerData = theOwnerData;
@@ -40,7 +47,25 @@ void Model_ResultGroup::colorConfigInfo(std::string& theSection, std::string& th
 std::shared_ptr<GeomAPI_Shape> Model_ResultGroup::shape()
 {
   std::shared_ptr<GeomAPI_Shape> aResult;
-  if (myOwnerData) {
+  // obtain stored shape
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(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<std::shared_ptr<GeomAPI_Shape> > aSubs;
@@ -57,3 +82,23 @@ std::shared_ptr<GeomAPI_Shape> Model_ResultGroup::shape()
   }
   return aResult;
 }
+
+void Model_ResultGroup::store(const GeomShapePtr& theShape)
+{
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(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<TopoDS_Shape>();
+    if (aShape.IsNull())
+      return;  // null shape inside
+
+    // store the new shape as primitive
+    TNaming_Builder aBuilder(aShapeLab);
+    aBuilder.Generated(aShape);
+  }
+}
index aa0c068dd5014ad09ab6e7cfb5cd101d1afee0d5..68e549d327d6ba8b493855a8c9e4c138917753dd 100644 (file)
@@ -41,6 +41,11 @@ public:
   /// Returns the compound of selected entities
   MODEL_EXPORT virtual std::shared_ptr<GeomAPI_Shape> 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() {}
 
index 8644fc1cfda754e909db316bf36c11e9f54c4eee..040f2a05ccbe3fc36d579337519dbbf9a5d297d8 100644 (file)
@@ -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
index 2b811848733c1bbe2b93af5829b7aa8ef43762e4..abe6aa02599cb656bcd66a7f60d0044856004e3a 100644 (file)
@@ -28,6 +28,7 @@
 #include <ModuleBase_ActionInfo.h>
 #include <ModuleBase_Tools.h>
 
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_ResultBody.h>
@@ -35,8 +36,6 @@
 #include <Config_FeatureMessage.h>
 #include <Events_Loop.h>
 
-#include <CollectionPlugin_Group.h>
-
 QMap<QString, QString> 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");