Salome HOME
Merge remote-tracking branch 'remotes/origin/Operations_on_Groups'
authorazv <azv@opencascade.com>
Mon, 12 Aug 2019 05:36:58 +0000 (08:36 +0300)
committerazv <azv@opencascade.com>
Mon, 12 Aug 2019 05:36:58 +0000 (08:36 +0300)
61 files changed:
src/CollectionAPI/CMakeLists.txt
src/CollectionAPI/CollectionAPI.i
src/CollectionAPI/CollectionAPI_GroupAddition.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupAddition.h [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupIntersection.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupIntersection.h [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp [new file with mode: 0644]
src/CollectionAPI/CollectionAPI_GroupSubstraction.h [new file with mode: 0644]
src/CollectionPlugin/CMakeLists.txt
src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupAddition.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupIntersection.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h [new file with mode: 0644]
src/CollectionPlugin/CollectionPlugin_Plugin.cpp
src/CollectionPlugin/CollectionPlugin_Validators.cpp
src/CollectionPlugin/CollectionPlugin_Validators.h
src/CollectionPlugin/CollectionPlugin_msg_en.ts
src/CollectionPlugin/Test/TestGroupAddition.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupAddition_Error.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupIntersection.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupIntersection_Error.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py [new file with mode: 0644]
src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py [new file with mode: 0644]
src/CollectionPlugin/doc/CollectionPlugin.rst
src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_addition.py [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_intersection.py [new file with mode: 0644]
src/CollectionPlugin/doc/examples/group_substraction.py [new file with mode: 0644]
src/CollectionPlugin/doc/groupAdditionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/groupIntersectionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/groupSubstractionFeature.rst [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_addition.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_addition_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_intersection.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_intersection_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_substraction.png [new file with mode: 0644]
src/CollectionPlugin/doc/images/group_substraction_property_panel.png [new file with mode: 0644]
src/CollectionPlugin/group_addition_widget.xml [new file with mode: 0644]
src/CollectionPlugin/group_intersection_widget.xml [new file with mode: 0644]
src/CollectionPlugin/group_substraction_widget.xml [new file with mode: 0644]
src/CollectionPlugin/icons/group_addition.png [new file with mode: 0644]
src/CollectionPlugin/icons/group_intersection.png [new file with mode: 0644]
src/CollectionPlugin/icons/group_substraction.png [new file with mode: 0644]
src/CollectionPlugin/plugin-Collection.xml
src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_ResultGroup.cpp
src/Model/Model_ResultGroup.h
src/ModelAPI/ModelAPI_ResultGroup.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/PartSet/PartSet_Filters.cpp
src/PartSet/PartSet_IconFactory.cpp
src/PythonAPI/model/collection/__init__.py
src/XGUI/XGUI_Displayer.cpp

index 0b2815bdd7250efc16593edcce438936a3efd033..f5c90abee6966ff63ada5cd6274526537390f50b 100644 (file)
@@ -22,11 +22,17 @@ INCLUDE(Common)
 SET(PROJECT_HEADERS
   CollectionAPI.h
   CollectionAPI_Group.h
+  CollectionAPI_GroupAddition.h
+  CollectionAPI_GroupIntersection.h
+  CollectionAPI_GroupSubstraction.h
   CollectionAPI_Field.h
 )
 
 SET(PROJECT_SOURCES
   CollectionAPI_Group.cpp
+  CollectionAPI_GroupAddition.cpp
+  CollectionAPI_GroupIntersection.cpp
+  CollectionAPI_GroupSubstraction.cpp
   CollectionAPI_Field.cpp
 )
 
index c27d56cb22240e9bc29f2187c5b7deee85e2c28a..552a33d3d64f1089ba22a94b1763f353cfbcc815 100644 (file)
@@ -29,6 +29,9 @@
 
   #include "CollectionAPI.h"
   #include "CollectionAPI_Group.h"
+  #include "CollectionAPI_GroupAddition.h"
+  #include "CollectionAPI_GroupIntersection.h"
+  #include "CollectionAPI_GroupSubstraction.h"
   #include "CollectionAPI_Field.h"
 
 #endif // CollectionAPI_swig_H_
 
 // shared pointers
 %shared_ptr(CollectionAPI_Group)
+%shared_ptr(CollectionAPI_GroupAddition)
+%shared_ptr(CollectionAPI_GroupIntersection)
+%shared_ptr(CollectionAPI_GroupSubstraction)
 %shared_ptr(CollectionAPI_Field)
 
 // all supported interfaces
 %include "CollectionAPI_Group.h"
+%include "CollectionAPI_GroupAddition.h"
+%include "CollectionAPI_GroupIntersection.h"
+%include "CollectionAPI_GroupSubstraction.h"
 %include "CollectionAPI_Field.h"
diff --git a/src/CollectionAPI/CollectionAPI_GroupAddition.cpp b/src/CollectionAPI/CollectionAPI_GroupAddition.cpp
new file mode 100644 (file)
index 0000000..d0fecad
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2014-2019  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 "CollectionAPI_GroupAddition.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupAddition::CollectionAPI_GroupAddition(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupAddition::CollectionAPI_GroupAddition(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setGroupList(theGroupList);
+  }
+}
+
+CollectionAPI_GroupAddition::~CollectionAPI_GroupAddition()
+{
+}
+
+void CollectionAPI_GroupAddition::setGroupList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mygroupList);
+  execute();
+}
+
+void CollectionAPI_GroupAddition::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrList =
+      aBase->selectionList(CollectionPlugin_GroupAddition::LIST_ID());
+
+  theDumper << aBase << " = model.addGroupAddition(" << aDocName << ", "
+            << anAttrList << ")" << std::endl;
+}
+
+GroupAdditionPtr addGroupAddition(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(CollectionAPI_GroupAddition::ID());
+  return GroupAdditionPtr(new CollectionAPI_GroupAddition(aFeature, theGroupList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupAddition.h b/src/CollectionAPI/CollectionAPI_GroupAddition.h
new file mode 100644 (file)
index 0000000..102e84a
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef CollectionAPI_GroupAddition_H_
+#define CollectionAPI_GroupAddition_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupAddition.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupAddition
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Addition feature.
+class CollectionAPI_GroupAddition : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupAddition(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupAddition(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupAddition();
+
+  INTERFACE_1(CollectionPlugin_GroupAddition::ID(),
+              groupList, CollectionPlugin_GroupAddition::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Group list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setGroupList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupAddition> GroupAdditionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Addition feature.
+COLLECTIONAPI_EXPORT
+GroupAdditionPtr addGroupAddition(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                  const std::list<ModelHighAPI_Selection>& theGroupsList);
+
+#endif // CollectionAPI_GroupAddition_H_
diff --git a/src/CollectionAPI/CollectionAPI_GroupIntersection.cpp b/src/CollectionAPI/CollectionAPI_GroupIntersection.cpp
new file mode 100644 (file)
index 0000000..7d4fad7
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2014-2019  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 "CollectionAPI_GroupIntersection.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupIntersection::CollectionAPI_GroupIntersection(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupIntersection::CollectionAPI_GroupIntersection(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setGroupList(theGroupList);
+  }
+}
+
+CollectionAPI_GroupIntersection::~CollectionAPI_GroupIntersection()
+{
+}
+
+void CollectionAPI_GroupIntersection::setGroupList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mygroupList);
+  execute();
+}
+
+void CollectionAPI_GroupIntersection::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrList =
+      aBase->selectionList(CollectionPlugin_GroupIntersection::LIST_ID());
+
+  theDumper << aBase << " = model.addGroupIntersection(" << aDocName << ", "
+            << anAttrList << ")" << std::endl;
+}
+
+GroupIntersectionPtr addGroupIntersection(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      thePart->addFeature(CollectionAPI_GroupIntersection::ID());
+  return GroupIntersectionPtr(new CollectionAPI_GroupIntersection(aFeature, theGroupList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupIntersection.h b/src/CollectionAPI/CollectionAPI_GroupIntersection.h
new file mode 100644 (file)
index 0000000..007853c
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef CollectionAPI_GroupIntersection_H_
+#define CollectionAPI_GroupIntersection_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupIntersection.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupIntersection
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Intersection feature.
+class CollectionAPI_GroupIntersection : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupIntersection(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupIntersection(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                  const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupIntersection();
+
+  INTERFACE_1(CollectionPlugin_GroupIntersection::ID(),
+              groupList, CollectionPlugin_GroupIntersection::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Group list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setGroupList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupIntersection> GroupIntersectionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Intersection feature.
+COLLECTIONAPI_EXPORT
+GroupIntersectionPtr addGroupIntersection(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theGroupsList);
+
+#endif // CollectionAPI_GroupIntersection_H_
diff --git a/src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp b/src/CollectionAPI/CollectionAPI_GroupSubstraction.cpp
new file mode 100644 (file)
index 0000000..bdd6494
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (C) 2014-2019  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 "CollectionAPI_GroupSubstraction.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+CollectionAPI_GroupSubstraction::CollectionAPI_GroupSubstraction(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+CollectionAPI_GroupSubstraction::CollectionAPI_GroupSubstraction(
+    const std::shared_ptr<ModelAPI_Feature>& theFeature,
+    const std::list<ModelHighAPI_Selection>& theObjectsList,
+    const std::list<ModelHighAPI_Selection>& theToolsList)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    setObjectsList(theObjectsList);
+    setToolsList(theToolsList);
+  }
+}
+
+CollectionAPI_GroupSubstraction::~CollectionAPI_GroupSubstraction()
+{
+}
+
+void CollectionAPI_GroupSubstraction::setObjectsList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, myobjectsList);
+  execute();
+}
+
+void CollectionAPI_GroupSubstraction::setToolsList(
+    const std::list<ModelHighAPI_Selection>& theGroupList)
+{
+  fillAttribute(theGroupList, mytoolsList);
+  execute();
+}
+
+void CollectionAPI_GroupSubstraction::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anObjectsList =
+      aBase->selectionList(CollectionPlugin_GroupSubstraction::LIST_ID());
+  AttributeSelectionListPtr aToolsList =
+      aBase->selectionList(CollectionPlugin_GroupSubstraction::TOOLS_ID());
+
+  theDumper << aBase << " = model.addGroupSubstraction(" << aDocName << ", "
+            << anObjectsList << ", " << aToolsList << ")" << std::endl;
+}
+
+GroupSubstractionPtr addGroupSubstraction(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                        const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                        const std::list<ModelHighAPI_Selection>& theToolsList)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature =
+      thePart->addFeature(CollectionAPI_GroupSubstraction::ID());
+  return GroupSubstractionPtr(new CollectionAPI_GroupSubstraction(
+      aFeature, theObjectsList, theToolsList));
+}
diff --git a/src/CollectionAPI/CollectionAPI_GroupSubstraction.h b/src/CollectionAPI/CollectionAPI_GroupSubstraction.h
new file mode 100644 (file)
index 0000000..0e11992
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef CollectionAPI_GroupSubstraction_H_
+#define CollectionAPI_GroupSubstraction_H_
+
+#include "CollectionAPI.h"
+
+#include <CollectionPlugin_GroupSubstraction.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class CollectionAPI_GroupSubstraction
+/// \ingroup CPPHighAPI
+/// \brief Interface for Group Intersection feature.
+class CollectionAPI_GroupSubstraction : public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  COLLECTIONAPI_EXPORT
+  explicit CollectionAPI_GroupSubstraction(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  COLLECTIONAPI_EXPORT
+  CollectionAPI_GroupSubstraction(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                  const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                  const std::list<ModelHighAPI_Selection>& theToolsList);
+
+  /// Destructor.
+  COLLECTIONAPI_EXPORT
+  virtual ~CollectionAPI_GroupSubstraction();
+
+  INTERFACE_2(CollectionPlugin_GroupSubstraction::ID(),
+              objectsList, CollectionPlugin_GroupSubstraction::LIST_ID(),
+              ModelAPI_AttributeSelectionList, /** Objects list*/,
+              toolsList, CollectionPlugin_GroupSubstraction::TOOLS_ID(),
+              ModelAPI_AttributeSelectionList, /** Tools list*/)
+
+  /// Set main objects.
+  COLLECTIONAPI_EXPORT
+  void setObjectsList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Set tools.
+  COLLECTIONAPI_EXPORT
+  void setToolsList(const std::list<ModelHighAPI_Selection>& theGroupList);
+
+  /// Dump wrapped feature
+  COLLECTIONAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Group Addition object.
+typedef std::shared_ptr<CollectionAPI_GroupSubstraction> GroupSubstractionPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Group Substraction feature.
+COLLECTIONAPI_EXPORT
+GroupSubstractionPtr addGroupSubstraction(const std::shared_ptr<ModelAPI_Document>& thePart,
+                                          const std::list<ModelHighAPI_Selection>& theObjectsList,
+                                          const std::list<ModelHighAPI_Selection>& theToolsList);
+
+#endif // CollectionAPI_GroupSubstraction_H_
index 2e2ff961d3687bae504a1d0492e4bffebcc75bec..cfdaaa8e775422ae838d210e569f3b0fff4613ed 100644 (file)
@@ -31,6 +31,9 @@ SET(PROJECT_HEADERS
     CollectionPlugin.h
     CollectionPlugin_Plugin.h
     CollectionPlugin_Group.h
+    CollectionPlugin_GroupAddition.h
+    CollectionPlugin_GroupIntersection.h
+    CollectionPlugin_GroupSubstraction.h
     CollectionPlugin_Field.h
     CollectionPlugin_WidgetCreator.h
     CollectionPlugin_WidgetField.h
@@ -44,6 +47,9 @@ SET(PROJECT_MOC_HEADERS
 SET(PROJECT_SOURCES
     CollectionPlugin_Plugin.cpp
     CollectionPlugin_Group.cpp
+    CollectionPlugin_GroupAddition.cpp
+    CollectionPlugin_GroupIntersection.cpp
+    CollectionPlugin_GroupSubstraction.cpp
     CollectionPlugin_Field.cpp
     CollectionPlugin_WidgetCreator.cpp
     CollectionPlugin_WidgetField.cpp
@@ -53,6 +59,9 @@ SET(PROJECT_SOURCES
 SET(XML_RESOURCES
   plugin-Collection.xml
   group_widget.xml
+  group_addition_widget.xml
+  group_intersection_widget.xml
+  group_substraction_widget.xml
 )
 
 SET(TEXT_RESOURCES
@@ -128,4 +137,11 @@ ADD_UNIT_TESTS(
                TestGroupMove19.py
                TestGroupMove20.py
                TestGroupShareTopology.py
+               TestGroupAddition.py
+               TestGroupAddition_Error.py
+               TestGroupIntersection.py
+               TestGroupIntersection_Error.py
+               TestGroupSubstraction.py
+               TestGroupSubstraction_Error1.py
+               TestGroupSubstraction_Error2.py
 )
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp b/src/CollectionPlugin/CollectionPlugin_GroupAddition.cpp
new file mode 100644 (file)
index 0000000..c27826c
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2014-2019  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 "CollectionPlugin_GroupAddition.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#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_GroupAddition::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+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)
+{
+  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
new file mode 100644 (file)
index 0000000..17b1ed1
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef COLLECTIONPLUGIN_GROUPADDITION_H_
+#define COLLECTIONPLUGIN_GROUPADDITION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_Group.h"
+
+/**\class CollectionPlugin_GroupAddition
+ * \ingroup Plugins
+ * \brief Merge several groups of same shape type into single group.
+ */
+class CollectionPlugin_GroupAddition : public CollectionPlugin_Group
+{
+ public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupAddition");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected entities list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupAddition::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Result of groups is created on the fly and don't stored to the document
+  COLLECTIONPLUGIN_EXPORT virtual bool isPersistentResult() {return true;}
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupAddition();
+
+};
+
+#endif
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp b/src/CollectionPlugin/CollectionPlugin_GroupIntersection.cpp
new file mode 100644 (file)
index 0000000..e74ba47
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright (C) 2014-2019  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 "CollectionPlugin_GroupIntersection.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
+
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShape;
+
+CollectionPlugin_GroupIntersection::CollectionPlugin_GroupIntersection()
+{
+}
+
+void CollectionPlugin_GroupIntersection::initAttributes()
+{
+  data()->addAttribute(CollectionPlugin_GroupIntersection::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+static void explodeCompound(const GeomShapePtr& theCompound, SetOfShape& theSet)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+    theSet.insert(anIt.current());
+}
+
+static void keepCommonShapes(const GeomShapePtr& theCompound, ListOfShape& theShapes)
+{
+  if (theShapes.empty()) {
+    for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+      theShapes.push_back(anIt.current());
+  }
+  else {
+    SetOfShape aSubs;
+    explodeCompound(theCompound, aSubs);
+
+    ListOfShape::iterator anIt = theShapes.begin();
+    while (anIt != theShapes.end()) {
+      if (aSubs.find(*anIt) == aSubs.end()) {
+        // the shape is not found
+        ListOfShape::iterator aRemoveIt = anIt++;
+        theShapes.erase(aRemoveIt);
+      }
+      else
+        ++anIt;
+    }
+  }
+}
+
+void CollectionPlugin_GroupIntersection::execute()
+{
+  ResultGroupPtr aGroup = document()->createGroup(data());
+  // clean the result of the operation
+  aGroup->store(GeomShapePtr());
+
+  // shapes containing in each group
+  ListOfShape aCommon;
+
+  // collect shapes containing in all groups
+  AttributeSelectionListPtr aSelectedGroups = selectionList(LIST_ID());
+  for (int anIndex = 0; anIndex < aSelectedGroups->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = aSelectedGroups->value(anIndex);
+    ResultGroupPtr aCurGroup =
+        std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    keepCommonShapes(aCurGroup->shape(), aCommon);
+    if (aCommon.empty())
+      break;
+  }
+
+  if (aCommon.empty()) {
+    setError("Error: Empty result.");
+    removeResults(0);
+  }
+  else {
+    GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aCommon);
+    aGroup->store(aCompound);
+    setResult(aGroup);
+  }
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupIntersection.h b/src/CollectionPlugin/CollectionPlugin_GroupIntersection.h
new file mode 100644 (file)
index 0000000..115f3f5
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef COLLECTIONPLUGIN_GROUPINTERSECTION_H_
+#define COLLECTIONPLUGIN_GROUPINTERSECTION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_Group.h"
+
+/**\class CollectionPlugin_GroupIntersection
+ * \ingroup Plugins
+ * \brief Merge several groups of same shape type into single group.
+ */
+class CollectionPlugin_GroupIntersection : public CollectionPlugin_Group
+{
+ public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupIntersection");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected entities list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupIntersection::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Result of groups is created on the fly and don't stored to the document
+  COLLECTIONPLUGIN_EXPORT virtual bool isPersistentResult() {return true;}
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupIntersection();
+
+};
+
+#endif
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp b/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.cpp
new file mode 100644 (file)
index 0000000..18f0aca
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) 2014-2019  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 "CollectionPlugin_GroupSubstraction.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultGroup.h>
+
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShape;
+
+CollectionPlugin_GroupSubstraction::CollectionPlugin_GroupSubstraction()
+{
+}
+
+void CollectionPlugin_GroupSubstraction::initAttributes()
+{
+  data()->addAttribute(CollectionPlugin_GroupSubstraction::LIST_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(CollectionPlugin_GroupSubstraction::TOOLS_ID(),
+                       ModelAPI_AttributeSelectionList::typeId());
+}
+
+static void explodeCompound(const GeomShapePtr& theCompound, SetOfShape& theSet)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next())
+    theSet.insert(anIt.current());
+}
+
+static void subtractLists(const GeomShapePtr& theCompound,
+                          const SetOfShape& theExclude,
+                                ListOfShape& theResult)
+{
+  for (GeomAPI_ShapeIterator anIt(theCompound); anIt.more(); anIt.next()) {
+    GeomShapePtr aCurrent = anIt.current();
+    if (theExclude.find(aCurrent) != theExclude.end())
+      continue; // shape has to be excluded
+    // check the shape is already in the list
+    ListOfShape::iterator anIt2 = theResult.begin();
+    for (; anIt2 != theResult.end(); ++anIt2)
+      if (aCurrent->isEqual(*anIt2))
+        break;
+    if (anIt2 == theResult.end())
+      theResult.push_back(aCurrent);
+  }
+}
+
+void CollectionPlugin_GroupSubstraction::execute()
+{
+  ResultGroupPtr aGroup = document()->createGroup(data());
+  // clean the result of the operation
+  aGroup->store(GeomShapePtr());
+
+  // collect shapes to be excluded (tools)
+  SetOfShape aShapesToExclude;
+  AttributeSelectionListPtr aTools = selectionList(TOOLS_ID());
+  for (int anIndex = 0; anIndex < aTools->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = aTools->value(anIndex);
+    ResultGroupPtr aCurGroup =
+      std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    explodeCompound(aCurGroup->shape(), aShapesToExclude);
+  }
+
+  // keep only shapes that should not be excluded
+  ListOfShape aCut;
+  AttributeSelectionListPtr anObjects = selectionList(LIST_ID());
+  for (int anIndex = 0; anIndex < anObjects->size(); ++anIndex) {
+    AttributeSelectionPtr aCurSelection = anObjects->value(anIndex);
+    ResultGroupPtr aCurGroup =
+        std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aCurSelection->context());
+    subtractLists(aCurGroup->shape(), aShapesToExclude, aCut);
+    if (aCut.empty())
+      break;
+  }
+
+  if (aCut.empty()) {
+    setError("Error: Empty result.");
+    removeResults(0);
+  }
+  else {
+    GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aCut);
+    aGroup->store(aCompound);
+    setResult(aGroup);
+  }
+}
diff --git a/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h b/src/CollectionPlugin/CollectionPlugin_GroupSubstraction.h
new file mode 100644 (file)
index 0000000..3fcd743
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (C) 2014-2019  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
+//
+
+#ifndef COLLECTIONPLUGIN_GROUPSUBSTRACTION_H_
+#define COLLECTIONPLUGIN_GROUPSUBSTRACTION_H_
+
+#include "CollectionPlugin.h"
+#include "CollectionPlugin_Group.h"
+
+/**\class CollectionPlugin_GroupSubstraction
+ * \ingroup Plugins
+ * \brief Remove all elements in "objects" groups which contain in "tools" groups.
+ */
+class CollectionPlugin_GroupSubstraction : public CollectionPlugin_Group
+{
+ public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_GROUP_ID("GroupSubstraction");
+    return MY_GROUP_ID;
+  }
+  /// attribute name of selected objects list
+  inline static const std::string& LIST_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("group_list");
+    return MY_GROUP_LIST_ID;
+  }
+  /// attribute name of selected tools list
+  inline static const std::string& TOOLS_ID()
+  {
+    static const std::string MY_GROUP_LIST_ID("tools_list");
+    return MY_GROUP_LIST_ID;
+  }
+
+  /// Returns the kind of a feature
+  COLLECTIONPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = CollectionPlugin_GroupSubstraction::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new group result if needed
+  COLLECTIONPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  COLLECTIONPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Result of groups is created on the fly and don't stored to the document
+  COLLECTIONPLUGIN_EXPORT virtual bool isPersistentResult() {return true;}
+
+  /// Use plugin manager for features creation
+  CollectionPlugin_GroupSubstraction();
+
+};
+
+#endif
index 7b0fc28e1e4210a783f0c73411daa334484bb8d9..8a62c07a803e2626c71b4d4a655a5b1f7fd6834c 100644 (file)
@@ -20,6 +20,9 @@
 #include <CollectionPlugin_Plugin.h>
 
 #include <CollectionPlugin_Group.h>
+#include <CollectionPlugin_GroupAddition.h>
+#include <CollectionPlugin_GroupIntersection.h>
+#include <CollectionPlugin_GroupSubstraction.h>
 #include <CollectionPlugin_Field.h>
 #include <CollectionPlugin_Validators.h>
 #include <ModelAPI_Session.h>
@@ -45,6 +48,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);
@@ -56,6 +61,12 @@ FeaturePtr CollectionPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new CollectionPlugin_Group);
   } else if (theFeatureID == CollectionPlugin_Field::ID()) {
     return FeaturePtr(new CollectionPlugin_Field);
+  } else if (theFeatureID == CollectionPlugin_GroupAddition::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupAddition);
+  } else if (theFeatureID == CollectionPlugin_GroupIntersection::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupIntersection);
+  } else if (theFeatureID == CollectionPlugin_GroupSubstraction::ID()) {
+    return FeaturePtr(new CollectionPlugin_GroupSubstraction);
   }
 
   // feature of such kind is not found
index d644c13f64817c4bc9f0da5fa700e3ddaea72fe1..7ef185389a1e2cb071ed5c88c8f659c62e61f5b7 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,59 @@ bool CollectionPlugin_FieldValidator::isValid(const FeaturePtr& theFeature,
   theError = "Selection list is not initialized";
   return false;
 }
+
+static bool isGroupTypeCorrect(const AttributeSelectionPtr& theSelection,
+                               std::string& theType,
+                               Events_InfoMessage& theError)
+{
+  // applicable the groups only
+  ResultPtr aGroupResult = theSelection->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 (theType.empty())
+    theType = aGroupType;
+  else if (theType != aGroupType) {
+    theError = "Error: Groups should have same type";
+    return false;
+  }
+  return true;
+}
+
+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);
+    if (!isGroupTypeCorrect(aCurSelection, aType, theError))
+      return false;
+  }
+  // check types of all selection lists are the same
+  for (std::list<std::string>::const_iterator aParIt = theArguments.begin();
+       aParIt != theArguments.end() && !aType.empty(); ++aParIt) {
+    AttributeSelectionListPtr aCurList = anOwner->selectionList(*aParIt);
+    if (aCurList->size() == 0)
+      continue;
+    AttributeSelectionPtr aCurSelection = aCurList->value(0);
+    if (!isGroupTypeCorrect(aCurSelection, aType, theError))
+      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 061f3923dee325bbad096d981a30234e417c17fb..3c2d28234f0d7a1e12046faff1037271fad59caa 100644 (file)
       <translation>Components are not selected</translation>
     </message>
   </context>
+  <context>
+    <name>GroupIntersection:EmptyResult</name>
+    <message>
+      <source>Error: Empty result.</source>
+      <translation>Error: Empty result.</translation>
+    </message>
+  </context>
 
 </TS>
diff --git a/src/CollectionPlugin/Test/TestGroupAddition.py b/src/CollectionPlugin/Test/TestGroupAddition.py
new file mode 100644 (file)
index 0000000..a5e88cc
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupAddition_1, 1)
+model.testNbSubResults(GroupAddition_1, [0])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.FACE, [3])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(GroupAddition_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(GroupAddition_1, [300])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupAddition_Error.py b/src/CollectionPlugin/Test/TestGroupAddition_Error.py
new file mode 100644 (file)
index 0000000..b69a249
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+GroupAddition_2 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("FACE", "Box_1_1/Front")])
+model.end()
+
+assert(GroupAddition_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupIntersection.py b/src/CollectionPlugin/Test/TestGroupIntersection.py
new file mode 100644 (file)
index 0000000..e53bfb1
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+Group_3_objects = [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Right"), model.selection("FACE", "Box_1_1/Top")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupIntersection_1, 1)
+model.testNbSubResults(GroupIntersection_1, [0])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(GroupIntersection_1, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(GroupIntersection_1, [100])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupIntersection_Error.py b/src/CollectionPlugin/Test/TestGroupIntersection_Error.py
new file mode 100644 (file)
index 0000000..cfa9601
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Right")])
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
+
+assert(GroupIntersection_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction.py b/src/CollectionPlugin/Test/TestGroupSubstraction.py
new file mode 100644 (file)
index 0000000..98669ca
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")], [model.selection("COMPOUND", "Group_3"), model.selection("COMPOUND", "Group_4")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupSubstraction_1, 1)
+model.testNbSubResults(GroupSubstraction_1, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.FACE, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.EDGE, [3])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.VERTEX, [6])
+
+assert(model.checkPythonDump())
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py b/src/CollectionPlugin/Test/TestGroupSubstraction_Error1.py
new file mode 100644 (file)
index 0000000..65ba668
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2")])
+model.end()
+
+assert(GroupSubstraction_1.feature().error() != "")
diff --git a/src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py b/src/CollectionPlugin/Test/TestGroupSubstraction_Error2.py
new file mode 100644 (file)
index 0000000..46967dd
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (C) 2014-2019  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Front")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Top")])
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2"), model.selection("COMPOUND", "Group_3")])
+model.end()
+
+assert(GroupSubstraction_1.feature().error() != "")
index e31d778235bfd4f5e072efc9536f7b7ef10b07dd..2b83ddd8cfc0ba857884478d711d43ad92ba32be 100644 (file)
@@ -13,3 +13,6 @@ Collection plug-in deals with groups of geometrical entities created by selectio
 
    fieldFeature.rst
    groupFeature.rst
+   groupAdditionFeature.rst
+   groupIntersectionFeature.rst
+   groupSubstractionFeature.rst
diff --git a/src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst b/src/CollectionPlugin/doc/TUI_groupAdditionFeature.rst
new file mode 100644 (file)
index 0000000..ea9cbaf
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_addition:
+
+Create Group Addition
+=====================
+
+.. literalinclude:: examples/group_addition.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_addition.py>`
diff --git a/src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst b/src/CollectionPlugin/doc/TUI_groupIntersectionFeature.rst
new file mode 100644 (file)
index 0000000..37a7d8d
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_intersection:
+
+Create Group Intersection
+=========================
+
+.. literalinclude:: examples/group_intersection.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_intersection.py>`
diff --git a/src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst b/src/CollectionPlugin/doc/TUI_groupSubstractionFeature.rst
new file mode 100644 (file)
index 0000000..ca836f9
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_create_group_substraction:
+
+Create Group Substraction
+=========================
+
+.. literalinclude:: examples/group_substraction.py
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/group_substraction.py>`
diff --git a/src/CollectionPlugin/doc/examples/group_addition.py b/src/CollectionPlugin/doc/examples/group_addition.py
new file mode 100644 (file)
index 0000000..20f80fc
--- /dev/null
@@ -0,0 +1,14 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+                                      model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+GroupAddition_1 = model.addGroupAddition(Part_1_doc, [model.selection("COMPOUND", "Group_1"),
+                                                      model.selection("COMPOUND", "Group_2")])
+model.end()
diff --git a/src/CollectionPlugin/doc/examples/group_intersection.py b/src/CollectionPlugin/doc/examples/group_intersection.py
new file mode 100644 (file)
index 0000000..84cb476
--- /dev/null
@@ -0,0 +1,19 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+                                      model.selection("FACE", "Box_1_1/Left")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+Group_3 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Front"),
+                                      model.selection("FACE", "Box_1_1/Right"),
+                                      model.selection("FACE", "Box_1_1/Top")])
+GroupIntersection_1_objects = [model.selection("COMPOUND", "Group_1"),
+                               model.selection("COMPOUND", "Group_2"),
+                               model.selection("COMPOUND", "Group_3")]
+GroupIntersection_1 = model.addGroupIntersection(Part_1_doc, GroupIntersection_1_objects)
+model.end()
diff --git a/src/CollectionPlugin/doc/examples/group_substraction.py b/src/CollectionPlugin/doc/examples/group_substraction.py
new file mode 100644 (file)
index 0000000..75cf556
--- /dev/null
@@ -0,0 +1,33 @@
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Group_1_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"),
+                   model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Left]")]
+Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
+Group_2_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]")]
+Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
+Group_3_objects = [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"),
+                   model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]")]
+Group_3 = model.addGroup(Part_1_doc, Group_3_objects)
+Group_4_objects = [model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Bottom]"),
+                   model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Bottom]")]
+Group_4 = model.addGroup(Part_1_doc, Group_4_objects)
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc,
+                                                 [model.selection("COMPOUND", "Group_1"),
+                                                  model.selection("COMPOUND", "Group_2")],
+                                                 [model.selection("COMPOUND", "Group_3"),
+                                                  model.selection("COMPOUND", "Group_4")])
+model.end()
diff --git a/src/CollectionPlugin/doc/groupAdditionFeature.rst b/src/CollectionPlugin/doc/groupAdditionFeature.rst
new file mode 100644 (file)
index 0000000..568ca10
--- /dev/null
@@ -0,0 +1,37 @@
+.. |group_addition.icon|    image:: images/group_addition.png
+
+Group Addition
+==============
+
+Group addition produces a union of all the elements of the selected groups.
+To create a Group Addition in the active part:
+
+#. select in the Main Menu *Features - > Group Addition* item  or
+#. click |group_addition.icon| **Group Addition** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_addition_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group addition operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupAddition_n**.
+- The list of selected groups of the same type.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+
+Note, that operation is valid only for the groups of the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupAddition(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+
+    :param part: The current part object
+    :param list: A list of selected groups
+    :return: Created object.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_addition` operation.
diff --git a/src/CollectionPlugin/doc/groupIntersectionFeature.rst b/src/CollectionPlugin/doc/groupIntersectionFeature.rst
new file mode 100644 (file)
index 0000000..dadbd43
--- /dev/null
@@ -0,0 +1,37 @@
+.. |group_intersection.icon|    image:: images/group_intersection.png
+
+Group Intersection
+==================
+
+Group intersection produces a group of elements present in all the selected groups.
+To create a Group Intersection in the active part:
+
+#. select in the Main Menu *Features - > Group Intersection* item  or
+#. click |group_intersection.icon| **Group Intersection** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_intersection_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group intersection operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupIntersection_n**.
+- The list of selected groups of the same type.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+
+Note, that operation is valid only for the groups of the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupIntersection(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")])
+
+    :param part: The current part object
+    :param list: A list of selected groups
+    :return: Created object.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_intersection` operation.
diff --git a/src/CollectionPlugin/doc/groupSubstractionFeature.rst b/src/CollectionPlugin/doc/groupSubstractionFeature.rst
new file mode 100644 (file)
index 0000000..b6ac227
--- /dev/null
@@ -0,0 +1,40 @@
+.. |group_substraction.icon|    image:: images/group_substraction.png
+
+Group Substraction
+==================
+
+Group substraction produces a group containing all elements of the main groups but not present in the tool groups.
+To create a Group Substraction in the active part:
+
+#. select in the Main Menu *Features - > Group Substraction* item  or
+#. click |group_substraction.icon| **Group Substraction** button in the toolbar:
+
+The following property panel appears. 
+
+.. image:: images/group_substraction_property_panel.png
+  :align: center
+
+.. centered::
+  Create a group substraction operation
+
+Input fields:
+
+- **Name** defines the name of the group, by default, it is **GroupSubstraction_n**.
+- The list of main groups.  Multiple selection can be done manually in OCC 3D Viewer by mouse click with Shift button pressed or by rectangle selection. To delete entities from the list, select them and call pop-up menu *Delete* item.
+- The list of tool groups.  Selection approaches are the same as for the main groups.
+
+Note, that operation is valid only if all the main groups and all the tool groups have the same type.
+
+**TUI Command**:
+
+.. py:function:: model.addGroupSubstraction(Part_1_doc,
+                                       [model.selection("COMPOUND", "Group_1"), model.selection("COMPOUND", "Group_2")],
+                                       [model.selection("COMPOUND", "Group_3"), model.selection("COMPOUND", "Group_4")])
+
+    :param part: The current part object
+    :param list: A list of main groups
+    :param list: A list of tool groups
+    :return: Created object.
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_group_substraction` operation.
diff --git a/src/CollectionPlugin/doc/images/group_addition.png b/src/CollectionPlugin/doc/images/group_addition.png
new file mode 100644 (file)
index 0000000..6bc76e0
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_addition.png differ
diff --git a/src/CollectionPlugin/doc/images/group_addition_property_panel.png b/src/CollectionPlugin/doc/images/group_addition_property_panel.png
new file mode 100644 (file)
index 0000000..54904a1
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_addition_property_panel.png differ
diff --git a/src/CollectionPlugin/doc/images/group_intersection.png b/src/CollectionPlugin/doc/images/group_intersection.png
new file mode 100644 (file)
index 0000000..aba074c
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_intersection.png differ
diff --git a/src/CollectionPlugin/doc/images/group_intersection_property_panel.png b/src/CollectionPlugin/doc/images/group_intersection_property_panel.png
new file mode 100644 (file)
index 0000000..54db493
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_intersection_property_panel.png differ
diff --git a/src/CollectionPlugin/doc/images/group_substraction.png b/src/CollectionPlugin/doc/images/group_substraction.png
new file mode 100644 (file)
index 0000000..7db75ec
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_substraction.png differ
diff --git a/src/CollectionPlugin/doc/images/group_substraction_property_panel.png b/src/CollectionPlugin/doc/images/group_substraction_property_panel.png
new file mode 100644 (file)
index 0000000..543681f
Binary files /dev/null and b/src/CollectionPlugin/doc/images/group_substraction_property_panel.png differ
diff --git a/src/CollectionPlugin/group_addition_widget.xml b/src/CollectionPlugin/group_addition_widget.xml
new file mode 100644 (file)
index 0000000..6274511
--- /dev/null
@@ -0,0 +1,11 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute"/>
+  </multi_selector>
+</source>
diff --git a/src/CollectionPlugin/group_intersection_widget.xml b/src/CollectionPlugin/group_intersection_widget.xml
new file mode 100644 (file)
index 0000000..6274511
--- /dev/null
@@ -0,0 +1,11 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute"/>
+  </multi_selector>
+</source>
diff --git a/src/CollectionPlugin/group_substraction_widget.xml b/src/CollectionPlugin/group_substraction_widget.xml
new file mode 100644 (file)
index 0000000..b06929b
--- /dev/null
@@ -0,0 +1,16 @@
+<source>
+  <namevalue id="name"
+             label="Name"
+             placeholder="Please input the group name">
+  </namevalue>
+  <multi_selector id="group_list"
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="tools_list"/>
+  </multi_selector>
+  <multi_selector id="tools_list"
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="group_list"/>
+  </multi_selector>
+</source>
diff --git a/src/CollectionPlugin/icons/group_addition.png b/src/CollectionPlugin/icons/group_addition.png
new file mode 100644 (file)
index 0000000..6bc76e0
Binary files /dev/null and b/src/CollectionPlugin/icons/group_addition.png differ
diff --git a/src/CollectionPlugin/icons/group_intersection.png b/src/CollectionPlugin/icons/group_intersection.png
new file mode 100644 (file)
index 0000000..aba074c
Binary files /dev/null and b/src/CollectionPlugin/icons/group_intersection.png differ
diff --git a/src/CollectionPlugin/icons/group_substraction.png b/src/CollectionPlugin/icons/group_substraction.png
new file mode 100644 (file)
index 0000000..7db75ec
Binary files /dev/null and b/src/CollectionPlugin/icons/group_substraction.png differ
index 27057f56f81d62468e1d79f1235410329fe56840..25c6d0c71178b322a1570d15176826f8da734c74 100644 (file)
         </field-panel>
         <validator id="CollectionPlugin_FieldValidator"/>
       </feature>
+
+      <feature id="GroupAddition"
+        title="Group Addition"
+        tooltip="Join several groups to single group"
+        icon="icons/Collection/group_addition.png"
+        helpfile="groupAdditionFeature.html">
+        <source path="group_addition_widget.xml"/>
+      </feature>
+
+      <feature id="GroupIntersection"
+        title="Group Intersection"
+        tooltip="Get elements existing in all groups"
+        icon="icons/Collection/group_intersection.png"
+        helpfile="groupIntersectionFeature.html">
+        <source path="group_intersection_widget.xml"/>
+      </feature>
+
+      <feature id="GroupSubstraction"
+        title="Group Substraction"
+        tooltip="Exclude elements existing tool groups"
+        icon="icons/Collection/group_substraction.png"
+        helpfile="groupSubstractionFeature.html">
+        <source path="group_substraction_widget.xml"/>
+      </feature>
     </group>
   </workbench>
 </plugin>
index c3a38788782385f5fa00772b093daaa95fefc2fb..f5a45f605278f7a795aa3da5ff0615a5644554d5 100644 (file)
@@ -18,6 +18,7 @@
 //
 
 #include "FeaturesPlugin_Pipe.h"
+#include "FeaturesPlugin_Tools.h"
 
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
@@ -373,11 +374,12 @@ void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
     aResultBody->loadGeneratedShapes(thePipeAlgo, thePathShape, GeomAPI_Shape::EDGE);
 
   // Store from shapes.
-  storeShapes(aResultBody, theBaseShapes.front()->shapeType(), thePipeAlgo->fromShapes(), "From_");
+  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, thePipeAlgo->fromShapes(), ListOfShape(),
+                                           thePipeAlgo, thePipeAlgo->shape(), "From");
 
   // Store to shapes.
-  storeShapes(aResultBody, theBaseShapes.back()->shapeType(), thePipeAlgo->toShapes(), "To_");
-
+  FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, thePipeAlgo->toShapes(), ListOfShape(),
+                                           thePipeAlgo, thePipeAlgo->shape(), "To");
 
   setResult(aResultBody, theResultIndex);
 }
index e9c92ad53de831ba8267f4c58d38c73214489675..ff194dac58e821903d20d866074e6cb6efb238ad 100644 (file)
@@ -29,6 +29,7 @@
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Tools.h>
@@ -180,6 +181,9 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
     aSelLab.ForgetAllAttributes(true);
     TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
     selectPart(std::dynamic_pointer_cast<ModelAPI_Result>(theContext), theSubShape);
+  } else if (theContext->groupName() == ModelAPI_ResultGroup::group()) {
+    aSelLab.ForgetAllAttributes(true);
+    TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
   } else { // check the feature context: parent-Part of this feature should not be used
     FeaturePtr aFeatureContext = std::dynamic_pointer_cast<ModelAPI_Feature>(theContext);
     if (aFeatureContext.get()) {
@@ -892,8 +896,11 @@ void Model_AttributeSelection::selectSubShape(
     // the whole result selection check
     if (aSubShapeName.find('/') == std::string::npos) {
       ObjectPtr aRes = aDoc->objectByName(ModelAPI_ResultConstruction::group(), aSubShapeName);
-      if (!aRes.get())
+      if (!aRes.get()) {
         aRes = aDoc->objectByName(ModelAPI_ResultBody::group(), aSubShapeName);
+        if (!aRes.get())
+          aRes = aDoc->objectByName(ModelAPI_ResultGroup::group(), aSubShapeName);
+      }
       if (aRes.get()) {
         setValue(aRes, anEmptyShape);
         return;
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 409f1b4306313f2eb47a89eaae331be86122aa7d..ef6f1ee621e4e62e6e1d8153220b6f7791a9e2a9 100644 (file)
@@ -52,6 +52,7 @@
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
@@ -289,7 +290,8 @@ static void getShapeAndContext(const AttributeSelectionPtr& theAttrSelect,
     if (theAttrSelect->isGeometricalSelection() &&
         theShape.get() && theShape->shapeType() == GeomAPI_Shape::COMPOUND &&
         theContext.get() && !theShape->isEqual(theContext->shape()) &&
-        theContext->groupName() != ModelAPI_ResultPart::group()) {
+        theContext->groupName() != ModelAPI_ResultPart::group() &&
+        theContext->groupName() != ModelAPI_ResultGroup::group()) {
       GeomAPI_ShapeIterator anIt(theShape);
       theShape = anIt.current();
     }
index b528344ce493df558b99541aabaa011b1cdc12fd..40d74c1d20629effe4ebecb36d940559cc91d6ef 100644 (file)
@@ -1299,6 +1299,28 @@ std::string generateName(const AttributePtr& theAttribute,
   return aName;
 }
 
+bool isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2)
+{
+  // In case of compound we cannot rely on simple comparison method.
+  // If the compound is generated by Group feature then this compound is alwais new.
+  // So, we have to compare content of these compounds
+  if (theShape1.ShapeType() != theShape2.ShapeType())
+    return false;
+
+  if (theShape1.ShapeType() != TopAbs_COMPOUND)
+    return theShape1.IsSame(theShape2);
+
+  TopoDS_Iterator aIt1(theShape1);
+  TopoDS_Iterator aIt2(theShape2);
+
+  for (; aIt1.More() && aIt2.More(); aIt1.Next(), aIt2.Next()) {
+    if (!(aIt1.Value()).IsSame(aIt2.Value()))
+      return false;
+  }
+  return true;
+}
+
+
 } // namespace ModuleBase_Tools
 
 
index 4523b7d809106e23170060953120ac7bddf48a9e..d6e4c4c550ce7fb74d1510a9183f3d3e39e5ac96 100644 (file)
@@ -389,6 +389,12 @@ bool MODULEBASE_EXPORT isNameExist(const QString& theName, FeaturePtr theIgnoreP
 /// \theName a name of parameter
 FeaturePtr MODULEBASE_EXPORT findParameter(const QString& theName);
 
+/// Returns true if both shapes are the same. In case of compounds it
+/// compares their contents.
+/// \param theShape1 a first shape to compare
+/// \param theShape2 a second shape to compare
+/// \return true if both shapes are the same
+bool MODULEBASE_EXPORT isSameShape(const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2);
 
 //----------- Class members -------------
 /// Returns a name in the next form: attribute_feature_name/attribute_id
index b7e5ccbb1e62e2d116921ed8220e201ff44e65af..582161acee01d363bff427842edf2005bd48d2e5 100644 (file)
@@ -63,8 +63,7 @@ Standard_Boolean PartSet_GlobalFilter::IsOk(const Handle(SelectMgr_EntityOwner)&
           if (aResultGroupName == ModelAPI_ResultPart::group()) {
             SessionPtr aMgr = ModelAPI_Session::get();
             aValid = aMgr->activeDocument() == aMgr->moduleDocument();
-          } else if (aResultGroupName == ModelAPI_ResultGroup::group() ||
-                     aResultGroupName == ModelAPI_ResultField::group()) {
+          } else if (aResultGroupName == ModelAPI_ResultField::group()) {
             aValid = Standard_False;
           } else
             aValid = Standard_True;
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");
index 5718df5f5c99294827b246ce2663786c96da14c6..695d5303db9f11fd9b4f6c4fff916cab8315da47 100644 (file)
@@ -20,3 +20,4 @@
 """
 
 from CollectionAPI import addGroup, addField
+from CollectionAPI import addGroupAddition, addGroupIntersection, addGroupSubstraction
index 23753cf8ca2811567bb4dc9c5ceece3f3ab4d4af..099d61ad0968a1d1c75a621ebf3cfe0fa52bd1b4 100644 (file)
@@ -1097,17 +1097,21 @@ void XGUI_Displayer::AddOrRemoveSelectedShapes(Handle(AIS_InteractiveContext) th
                                              ::Iterator aShapeIt(theShapesToBeSelected);
       for (; aShapeIt.More(); aShapeIt.Next()) {
         const TopoDS_Shape& aParameterShape = aShapeIt.Key();
-        // isSame should be used here as it does not check orientation of shapes
-        // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
-        // different for Edges shapes in model shape and owner even if this is the same shape
-        if (aParameterShape.IsSame(aShape)) {
+        // In case of compound we cannot rely on simple comparison method.
+        // If the compound is generated by Group feature then this compound is alwais new.
+        // So, we have to compare content of these compounds
+
+          // isSame should be used here as it does not check orientation of shapes
+          // despite on isEqual of shapes or IsBound for shape in QMap. Orientation is
+          // different for Edges shapes in model shape and owner even if this is the same shape
+        if (ModuleBase_Tools::isSameShape(aParameterShape, aShape)) {
           Handle(AIS_InteractiveObject) anOwnerPresentation =
-                            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+            Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
           NCollection_Map<Handle(AIS_InteractiveObject)> aPresentations =
-                                      theShapesToBeSelected.Find(aParameterShape);
+            theShapesToBeSelected.Find(aParameterShape);
           if (aPresentations.Contains(anOwnerPresentation)) {
             theContext->AddOrRemoveSelected(anOwner, Standard_False);
-            anOwner->SetSelected (Standard_True);
+            anOwner->SetSelected(Standard_True);
             // collect selected presentations to do not select them if compsolid is selected
             if (!aSelectedPresentations.Contains(anOwnerPresentation))
               aSelectedPresentations.Add(anOwnerPresentation);