Salome HOME
Task 2.5. Combination operations on Groups (issue #2935)
authorazv <azv@opencascade.com>
Thu, 8 Aug 2019 12:15:52 +0000 (15:15 +0300)
committerazv <azv@opencascade.com>
Thu, 8 Aug 2019 12:15:52 +0000 (15:15 +0300)
Implement Group Substraction feature.

17 files changed:
src/CollectionAPI/CMakeLists.txt
src/CollectionAPI/CollectionAPI.i
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_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/Test/TestGroupAddition.py
src/CollectionPlugin/Test/TestGroupAddition_Error.py
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/group_substraction_widget.xml
src/CollectionPlugin/plugin-Collection.xml
src/PythonAPI/model/collection/__init__.py

index 0bf7bffa4ff751c3b2d09d53d9f7843e54d3ec89..f5c90abee6966ff63ada5cd6274526537390f50b 100644 (file)
@@ -24,6 +24,7 @@ SET(PROJECT_HEADERS
   CollectionAPI_Group.h
   CollectionAPI_GroupAddition.h
   CollectionAPI_GroupIntersection.h
+  CollectionAPI_GroupSubstraction.h
   CollectionAPI_Field.h
 )
 
@@ -31,6 +32,7 @@ SET(PROJECT_SOURCES
   CollectionAPI_Group.cpp
   CollectionAPI_GroupAddition.cpp
   CollectionAPI_GroupIntersection.cpp
+  CollectionAPI_GroupSubstraction.cpp
   CollectionAPI_Field.cpp
 )
 
index a4fbd35ec080e0d1db14dd9fd14165509644f886..552a33d3d64f1089ba22a94b1763f353cfbcc815 100644 (file)
@@ -31,6 +31,7 @@
   #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_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_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 77ef3615db4970732709ba0656d2c9edceb217f5..cfdaaa8e775422ae838d210e569f3b0fff4613ed 100644 (file)
@@ -33,6 +33,7 @@ SET(PROJECT_HEADERS
     CollectionPlugin_Group.h
     CollectionPlugin_GroupAddition.h
     CollectionPlugin_GroupIntersection.h
+    CollectionPlugin_GroupSubstraction.h
     CollectionPlugin_Field.h
     CollectionPlugin_WidgetCreator.h
     CollectionPlugin_WidgetField.h
@@ -48,6 +49,7 @@ SET(PROJECT_SOURCES
     CollectionPlugin_Group.cpp
     CollectionPlugin_GroupAddition.cpp
     CollectionPlugin_GroupIntersection.cpp
+    CollectionPlugin_GroupSubstraction.cpp
     CollectionPlugin_Field.cpp
     CollectionPlugin_WidgetCreator.cpp
     CollectionPlugin_WidgetField.cpp
@@ -139,4 +141,7 @@ ADD_UNIT_TESTS(
                TestGroupAddition_Error.py
                TestGroupIntersection.py
                TestGroupIntersection_Error.py
+               TestGroupSubstraction.py
+               TestGroupSubstraction_Error1.py
+               TestGroupSubstraction_Error2.py
 )
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 d8514f518b583a19fb6c97de7db4608bb97fd94b..8a62c07a803e2626c71b4d4a655a5b1f7fd6834c 100644 (file)
@@ -22,6 +22,7 @@
 #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>
@@ -64,6 +65,8 @@ FeaturePtr CollectionPlugin_Plugin::createFeature(std::string theFeatureID)
     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 caf64d0bbed7a6f8e264de786e131d5355a1f4a2..7ef185389a1e2cb071ed5c88c8f659c62e61f5b7 100644 (file)
@@ -45,6 +45,29 @@ bool CollectionPlugin_FieldValidator::isValid(const FeaturePtr& theFeature,
   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,
@@ -62,22 +85,18 @@ bool CollectionPlugin_GroupOperationAttributeValidator::isValid(
   std::string aType;
   for (int anIndex = 0; anIndex < aSelList->size(); ++anIndex) {
     AttributeSelectionPtr aCurSelection = aSelList->value(anIndex);
-    // applicable the groups only
-    ResultPtr aGroupResult = aCurSelection->context();
-    if (aGroupResult->groupName() != ModelAPI_ResultGroup::group()) {
-      theError = "Error: Groups can be selected only.";
+    if (!isGroupTypeCorrect(aCurSelection, aType, theError))
       return false;
-    }
-    // groups of same type can be selected only
-    FeaturePtr aGroupFeature = ModelAPI_Feature::feature(aGroupResult->data()->owner());
-    std::string aGroupType =
-        aGroupFeature->selectionList(CollectionPlugin_Group::LIST_ID())->selectionType();
-    if (aType.empty())
-      aType = aGroupType;
-    else if (aType != aGroupType) {
-      theError = "Error: Groups should have same type";
+  }
+  // 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 de66eb5270869958854274907bc6ad67a0df7fd7..a5e88cc4c2969c298ac3b349cb1fdd0d528a82b6 100644 (file)
@@ -27,7 +27,7 @@ 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
+model.end()
 
 from GeomAPI import *
 
index ad6934da27bb374702cf8211876bcbc2618feb68..b69a249391980218b4c3b53d2d9f11f61dd0b891 100644 (file)
@@ -28,6 +28,6 @@ Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"), mo
 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
+model.end()
 
 assert(GroupAddition_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 3a1f83feb772573df3df2b5e9777b445eddd0ea6..b06929b0e0d0f42df63625771869ec55f2486f5f 100644 (file)
@@ -1,15 +1,16 @@
 <source>
   <namevalue id="name"
-    label="Name"
-    placeholder="Please input the group name">
+             label="Name"
+             placeholder="Please input the group name">
   </namevalue>
   <multi_selector id="group_list"
-    tooltip="Select a set of objects"
-    type_choice="Vertices Edges Faces Solids"
-    use_choice="true"
-    clear_in_neutral_point="false"
-    filter_points="false"
-    same_topology="true">
-    <validator id="GeomValidators_BodyShapes"/>
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="tools_list"/>
   </multi_selector>
-</source>
\ No newline at end of file
+  <multi_selector id="tools_list"
+                  tooltip="Select a set of groups"
+                  type_choice="objects">
+    <validator id="CollectionPlugin_OperationAttribute" parameters="group_list"/>
+  </multi_selector>
+</source>
index 29520489847df724966e59066d934c4cf4159558..37a05a42d173dda6d86f61b2537d61aaa39b4d32 100644 (file)
         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"
+        apply_continue="true"
+        helpfile="groupSubstractionFeature.html">
+        <source path="group_substraction_widget.xml"/>
+      </feature>
     </group>
   </workbench>
 </plugin>
index 3e96808fd88800f976f3e6b8b574f0dcac62b6b6..695d5303db9f11fd9b4f6c4fff916cab8315da47 100644 (file)
@@ -20,4 +20,4 @@
 """
 
 from CollectionAPI import addGroup, addField
-from CollectionAPI import addGroupAddition, addGroupIntersection
+from CollectionAPI import addGroupAddition, addGroupIntersection, addGroupSubstraction