Salome HOME
Unit tests for already implemented filters.
authorazv <azv@opencascade.com>
Mon, 24 Jun 2019 12:30:49 +0000 (15:30 +0300)
committerazv <azv@opencascade.com>
Mon, 24 Jun 2019 12:30:49 +0000 (15:30 +0300)
16 files changed:
src/FiltersAPI/FiltersAPI_Feature.cpp
src/FiltersAPI/FiltersAPI_Filter.h
src/FiltersAPI/FiltersAPI_Selection.cpp
src/FiltersAPI/FiltersAPI_Selection.h
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_HorizontalFace.cpp
src/FiltersPlugin/FiltersPlugin_VerticalFace.cpp
src/FiltersPlugin/Test/TestFilter_BelongsTo.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_HorizontalFaces.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_OnPlane.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_VerticalFaces.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilters.py [new file with mode: 0644]
src/Model/Model_Session.cpp
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_swig.h
src/PythonAPI/model/tests/tests.py

index 9829d9b872475008c4809d3f92747c00df349744..ea9894fd665bdfeab222c7019853af7a2f1cfbdf 100644 (file)
@@ -22,6 +22,7 @@
 #include <ModelAPI_Feature.h>
 
 #include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
 
 FiltersAPI_Feature::FiltersAPI_Feature(
     const std::shared_ptr<ModelAPI_Feature> & theFeature)
@@ -41,6 +42,19 @@ void FiltersAPI_Feature::setFilters(const std::list<FilterAPIPtr>& theFilters)
        anIt != theFilters.end(); ++anIt) {
     aBase->addFilter((*anIt)->name());
     aBase->setReversed((*anIt)->name(), (*anIt)->isReversed());
+
+    const std::list<ModelHighAPI_Selection>& anArgs = (*anIt)->arguments();
+    if (!anArgs.empty()) {
+      // find selectionList argument and fill it
+      std::list<AttributePtr> aFilterArgs = aBase->filterArgs((*anIt)->name());
+      for (std::list<AttributePtr>::iterator aFIt = aFilterArgs.begin();
+           aFIt != aFilterArgs.end(); ++aFIt) {
+        AttributeSelectionListPtr aSelList =
+            std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aFIt);
+        if (aSelList)
+          fillAttribute(anArgs, aSelList);
+      }
+    }
   }
 }
 
index 7621b819bcd394223ddfcf1725ee597f4b8a220a..27b576b976b1b87c6ea8ae2d6e6a7f9c2a43d1d8 100644 (file)
@@ -51,6 +51,7 @@ public:
 
   const std::string& name() const { return myName; }
   bool isReversed() const { return myReversed; }
+  const std::list<ModelHighAPI_Selection>& arguments() const { return myFilterArguments; }
 
   /// Dump wrapped feature
   FILTERSAPI_EXPORT
index 93a4444d92826fc518672c035b049280811ff059..dd4736a1303bbb1909abf829325f52484cf8911a 100644 (file)
@@ -29,6 +29,11 @@ FiltersAPI_Selection::~FiltersAPI_Selection()
 {
 }
 
+FiltersFeaturePtr FiltersAPI_Selection::feature() const
+{
+  return myFilterFeature;
+}
+
 // ================================================================================================
 FiltersAPI_Selection filters(const std::shared_ptr<ModelAPI_Document>& thePart,
                              const std::list<FilterAPIPtr>& theFilters)
index 10e9b456000054090add844a314c779445d6c9bd..4a0cc3742f37195a90ca2ce2d64b62f9d14c09be 100644 (file)
@@ -40,6 +40,10 @@ public:
   /// Destructor
   FILTERSAPI_EXPORT
   virtual ~FiltersAPI_Selection();
+
+  /// Return filters feature
+  FILTERSAPI_EXPORT
+  FiltersFeaturePtr feature() const;
 };
 
 /// Create list of filters
index a764abe5e432f0e64520e8106f4c56d18f77eda1..4ff7f61f2a009ce5ced1ea38061920d03db55bad 100644 (file)
@@ -18,6 +18,7 @@
 ##
 
 INCLUDE(Common)
+INCLUDE(UnitTest)
 
 SET(PROJECT_HEADERS
     FiltersPlugin.h
@@ -64,3 +65,11 @@ INCLUDE_DIRECTORIES(
 
 INSTALL(TARGETS Filters DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
 INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+
+ADD_UNIT_TESTS(
+  TestFilters.py
+  TestFilter_BelongsTo.py
+  TestFilter_OnPlane.py
+  TestFilter_HorizontalFaces.py
+  TestFilter_VerticalFaces.py
+)
index c602e421e7e872ce5964b620c561eb78ecf73d6b..6bda6a6cfcc802383b80103191c133f28fdbbeea 100644 (file)
@@ -30,7 +30,7 @@ bool FiltersPlugin_HorizontalFace::isSupported(GeomAPI_Shape::ShapeType theType)
 bool FiltersPlugin_HorizontalFace::isOk(
   const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const
 {
-  if (!theShape->isPlanar())
+  if (!theShape->isFace() || !theShape->isPlanar())
     return false;
   GeomFacePtr aFace(new GeomAPI_Face(theShape));
 
index 97235249f66144c888292877208d6bacecd3fb71..49fd944c6e7098826aa69d809b79ed56dabceec6 100644 (file)
@@ -33,14 +33,12 @@ bool FiltersPlugin_VerticalFace::isSupported(GeomAPI_Shape::ShapeType theType) c
 bool FiltersPlugin_VerticalFace::isOk(
   const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const
 {
-  if (!theShape->isFace())
+  if (!theShape->isFace() || !theShape->isPlanar())
     return false;
-  if (theShape->isPlanar()) {
-    GeomFacePtr aFace(new GeomAPI_Face(theShape));
 
-    GeomPlanePtr aPlane = aFace->getPlane();
-    GeomDirPtr aDir = aPlane->direction();
-    return fabs(aDir->z()) <= 1.e-7;
-  }
-  return false;
+  GeomFacePtr aFace(new GeomAPI_Face(theShape));
+
+  GeomPlanePtr aPlane = aFace->getPlane();
+  GeomDirPtr aDir = aPlane->direction();
+  return fabs(aDir->z()) <= 1.e-7;
 }
diff --git a/src/FiltersPlugin/Test/TestFilter_BelongsTo.py b/src/FiltersPlugin/Test/TestFilter_BelongsTo.py
new file mode 100644 (file)
index 0000000..420a173
--- /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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+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)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 20, 2, model.selection("EDGE", "PartSet/OY"), 20, 3)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "BelongsTo", args = [model.selection("SOLID", "LinearCopy_1_1_1"), model.selection("SOLID", "Translation_1_1")])])
+model.end()
+
+Reference = {}
+# Faces of the original box
+ResultBox_1 = LinearCopy_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+# Faces of another box
+ResultBox_2 = LinearCopy_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+# Faces of the cylinder
+ResultCylinder_1 = Translation_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = True
+  exp.next()
+# Edges of the original box
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+# Edges of another box
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+# Edges of the cylinder
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = True
+  exp.next()
+# Vertices of the original box
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+# Vertices of another box
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+# Vertices of the cylinder
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = True
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_HorizontalFaces.py b/src/FiltersPlugin/Test/TestFilter_HorizontalFaces.py
new file mode 100644 (file)
index 0000000..d019ff8
--- /dev/null
@@ -0,0 +1,63 @@
+# 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)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 20, 2, model.selection("EDGE", "PartSet/OY"), 20, 3)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "HorizontalFaces")])
+model.end()
+
+Reference = {
+    # Faces of the original box
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Left"): False,
+    # Translated box
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Left"): False,
+    # Box translated along another direction
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Bottom"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Left"): False,
+    # Faces of the cylinder
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"): True,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_3"): True,
+    # Edges and vertices are not applicable
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    }
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_OnPlane.py b/src/FiltersPlugin/Test/TestFilter_OnPlane.py
new file mode 100644 (file)
index 0000000..fa07283
--- /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
+#
+
+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)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 20, 2, model.selection("EDGE", "PartSet/OY"), 20, 3)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OnPlane", args = [model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Top"), model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Left")])])
+model.end()
+
+Reference = {
+    # Faces of the original box
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Left"): True,
+    # Translated box
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Left"): True,
+    # Box translated along another direction
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Top"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Left"): False,
+    # Faces of the cylinder
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"): True,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_3"): False,
+    # Edges of the original box
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    # Edges of translated box
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Left][LinearCopy_1_1_6/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Right][LinearCopy_1_1_6/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Front][LinearCopy_1_1_6/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Back][LinearCopy_1_1_6/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Back][LinearCopy_1_1_6/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Front][LinearCopy_1_1_6/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Front][LinearCopy_1_1_6/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Back][LinearCopy_1_1_6/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Left][LinearCopy_1_1_6/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Right][LinearCopy_1_1_6/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Front][LinearCopy_1_1_6/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_6/MF:Translated&Box_1_1/Back][LinearCopy_1_1_6/MF:Translated&Box_1_1/Bottom]"): False,
+    # Edges of the cylinder
+    model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"): True,
+    model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_3]"): False,
+    model.selection("EDGE", "([Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2])([Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_3])"): True,
+    # Vertices of the original box
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    # Vertices of translated box
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    }
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_VerticalFaces.py b/src/FiltersPlugin/Test/TestFilter_VerticalFaces.py
new file mode 100644 (file)
index 0000000..b60dfdb
--- /dev/null
@@ -0,0 +1,63 @@
+# 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)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 20, 2, model.selection("EDGE", "PartSet/OY"), 20, 3)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "VerticalFaces")])
+model.end()
+
+Reference = {
+    # Faces of the original box
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Top"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Front"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Back"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Right"): True,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Left"): True,
+    # Translated box
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Top"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Front"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Back"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Right"): True,
+    model.selection("FACE", "LinearCopy_1_1_2/MF:Translated&Box_1_1/Left"): True,
+    # Box translated along another direction
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Top"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Front"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Back"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Right"): True,
+    model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Box_1_1/Left"): True,
+    # Faces of the cylinder
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_3"): False,
+    # Edges and vertices are not applicable
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    }
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilters.py b/src/FiltersPlugin/Test/TestFilters.py
new file mode 100644 (file)
index 0000000..c08497f
--- /dev/null
@@ -0,0 +1,37 @@
+# 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
+from ModelAPI import *
+
+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/Bottom"), model.selection("FACE", "Box_1_1/Top"), model.filters(Part_1_doc, [model.addFilter(name = "BelongsTo", args = []), model.addFilter(name = "HorizontalFaces")])])
+model.end()
+
+aFactory = ModelAPI_Session.get().validators()
+
+GroupFeature = Group_1.feature()
+assert(aFactory.validate(GroupFeature))
+assert(GroupFeature.selectionList("group_list").size() == 2)
+
+assert(model.checkPythonDump())
index 5a8f6f736f9b8c6ae4725d05039ac4198bfa46af..c555fac10c53615b5babf88ca9a4042b45dc3945 100644 (file)
@@ -26,7 +26,7 @@
 #include <Model_Application.h>
 #include <Model_Events.h>
 #include <Model_Validator.h>
-#include <Model_Filter.h>
+#include <Model_FiltersFactory.h>
 #include <ModelAPI_Events.h>
 #include <Events_Loop.h>
 #include <Events_InfoMessage.h>
index b08f5daf1a1a63a4b598c5e8e266e9585babec26..5050456495a826d303854bc811c4d1f239a09ee5 100644 (file)
@@ -65,6 +65,7 @@
 %shared_ptr(ModelAPI_Feature)
 %shared_ptr(ModelAPI_CompositeFeature)
 %shared_ptr(ModelAPI_Data)
+%shared_ptr(ModelAPI_FiltersFeature)
 %shared_ptr(ModelAPI_Folder)
 %shared_ptr(ModelAPI_Attribute)
 %shared_ptr(ModelAPI_AttributeDocRef)
 %include "ModelAPI_ResultParameter.h"
 %include "ModelAPI_Tools.h"
 %include "ModelAPI_Folder.h"
+%include "ModelAPI_Filter.h"
+%include "ModelAPI_FiltersArgs.h"
+%include "ModelAPI_FiltersFactory.h"
+%include "ModelAPI_FiltersFeature.h"
 
 // std::list -> []
 %template(StringList) std::list<std::string>;
index 243359d684a5b228939fed03baa5a9cec24312fe..2187c2ae41cf1ca29cbb66a396da298566eec586 100644 (file)
   #include "ModelAPI_ResultField.h"
   #include "ModelAPI_Tools.h"
   #include "ModelAPI_Folder.h"
+  #include "ModelAPI_Filter.h"
+  #include "ModelAPI_FiltersArgs.h"
+  #include "ModelAPI_FiltersFactory.h"
+  #include "ModelAPI_FiltersFeature.h"
 
   #include <memory>
   #include <string>
index 0a99e7c48cd65b9b897f94dd3abc75f82178712e..17fd989ebadacdabb46b7053108995b156afd9fc 100644 (file)
@@ -20,7 +20,8 @@
 from GeomAlgoAPI import *
 from GeomAPI import *
 from GeomDataAPI import *
-from ModelAPI import ModelAPI_Feature
+from ModelAPI import ModelAPI_Feature, ModelAPI_Session
+from ModelHighAPI import *
 import math
 from salome.shaper.model import sketcher
 
@@ -321,3 +322,32 @@ def checkGroup(theGroup, theShapeType):
     assert(name != ""), "String empty"
     presented_names.add(name)
   assert(len(presented_names) == groupSelectionList.size()), "Some names are not unique"
+
+def createSubShape(thePartDoc, theModel, theSelection):
+  """ Create feature according to the type of the given subshape
+  """
+  if theSelection.shapeType() == "VERTEX":
+    return theModel.addVertex(thePartDoc, [theSelection])
+  elif theSelection.shapeType() == "EDGE":
+    return theModel.addEdge(thePartDoc, [theSelection])
+  elif theSelection.shapeType() == "FACE":
+    return theModel.addFace(thePartDoc, [theSelection])
+
+def checkFilter(thePartDoc, theModel, theFilter, theShapesList):
+  """ Check filter's work on specified shape.
+      Shapes given as a dictionary of selection and expected result.
+  """
+  aFiltersFactory = ModelAPI_Session.get().filters()
+  for sel, res in theShapesList.items():
+    needUndo = False
+    if sel.variantType() == ModelHighAPI_Selection.VT_ResultSubShapePair:
+      shape = sel.resultSubShapePair()[1]
+    else:
+      needUndo = True
+      theModel.begin()
+      subShapeFeature = createSubShape(thePartDoc, theModel, sel)
+      theModel.end()
+      shape = subShapeFeature.results()[0].resultSubShapePair()[0].shape()
+    assert(aFiltersFactory.isValid(theFilter.feature(), shape) == res)
+    if needUndo:
+      theModel.undo()