]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Implement filter "F12: Topologically connected Faces"
authorazv <azv@opencascade.com>
Mon, 8 Jul 2019 15:13:51 +0000 (18:13 +0300)
committerazv <azv@opencascade.com>
Mon, 8 Jul 2019 15:13:51 +0000 (18:13 +0300)
37 files changed:
src/FiltersAPI/FiltersAPI.i
src/FiltersAPI/FiltersAPI_Argument.cpp
src/FiltersAPI/FiltersAPI_Argument.h
src/FiltersAPI/FiltersAPI_Feature.cpp
src/FiltersAPI/FiltersAPI_Filter.cpp
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_Plugin.cpp
src/FiltersPlugin/FiltersPlugin_TopoConnectedFaces.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge3.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face3.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge3.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face3.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex3.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex1.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex2.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex3.py [new file with mode: 0644]
src/FiltersPlugin/filter-TopoConnectedFaces.xml [new file with mode: 0644]
src/GeomAPI/GeomAPI.i
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAPI/GeomAPI_Shape.h
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_swig.h
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_Filter.h

index 4c0e180848cf7c094eb7036b42c5da610cbfe676..31da0685b210b73fa98bc0047b2a887cfa4ece12 100644 (file)
@@ -74,7 +74,7 @@
           $1 = 0;
         }
       } else
-      if (!PyUnicode_Check(item))
+      if (!PyUnicode_Check(item) && !PyBool_Check(item))
         $1 = 0;
     }
   }
@@ -89,7 +89,7 @@
       PyObject * item = PySequence_GetItem($input, i);
       if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
         if (!temp_selection) {
-          PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection or string.");
+          PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection, string or boolean.");
           return NULL;
         }
         temp.push_back(FiltersAPI_Argument(*temp_selection));
@@ -99,7 +99,7 @@
       } else
       if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_string, $descriptor(std::string*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
         if (!temp_string) {
-          PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection or string.");
+          PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection, string or boolean.");
           return NULL;
         }
         temp.push_back(FiltersAPI_Argument(*temp_string));
       } else
       if (PyUnicode_Check(item)) {
         temp.push_back(FiltersAPI_Argument(PyUnicode_AsUTF8(item)));
+      } else
+      if (PyBool_Check(item)) {
+        temp.push_back(FiltersAPI_Argument(item == Py_True));
       } else {
-        PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection or string.");
+        PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection, string or boolean.");
         return NULL;
       }
       Py_DECREF(item);
     }
     $1 = &temp;
   } else {
-    PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection or std::string.");
+    PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_Selection, string or boolean.");
     return NULL;
   }
 }
index d4c77ab2f2af56872dd18dd36152e641e81c4ff7..d27819c4ea9dc2b55383354e4beab899a749be54 100644 (file)
@@ -23,6 +23,11 @@ FiltersAPI_Argument::FiltersAPI_Argument()
 {
 }
 
+FiltersAPI_Argument::FiltersAPI_Argument(const bool theValue)
+  : myBoolean(theValue)
+{
+}
+
 FiltersAPI_Argument::FiltersAPI_Argument(const std::string& theValue)
   : myValue(theValue)
 {
@@ -46,6 +51,10 @@ void FiltersAPI_Argument::dump(ModelHighAPI_Dumper& theDumper) const
 {
   if (mySelectionAttr)
     theDumper << mySelectionAttr;
-  else if (mySelection.variantType() == ModelHighAPI_Selection::VT_Empty)
-    theDumper << "\"" << myValue << "\"";
+  else if (mySelection.variantType() == ModelHighAPI_Selection::VT_Empty) {
+    if (myValue.empty())
+      theDumper << myBoolean;
+    else
+      theDumper << "\"" << myValue << "\"";
+  }
 }
index 2e3d2108a3d97ae2a27f32db5039cb532a790a70..19374e3b7e2eb8eed55d8b37b37fa22de23c3018 100644 (file)
@@ -36,6 +36,9 @@ class FiltersAPI_Argument
 public:
   FILTERSAPI_EXPORT FiltersAPI_Argument();
 
+  FILTERSAPI_EXPORT
+  FiltersAPI_Argument(const bool theValue);
+
   FILTERSAPI_EXPORT
   FiltersAPI_Argument(const std::string& theValue);
 
@@ -49,6 +52,7 @@ public:
   FILTERSAPI_EXPORT
   virtual ~FiltersAPI_Argument();
 
+  const bool boolean() const { return myBoolean; }
   const std::string& string() const { return myValue; }
   const ModelHighAPI_Selection& selection() const { return mySelection; }
 
@@ -57,6 +61,7 @@ public:
   void dump(ModelHighAPI_Dumper& theDumper) const;
 
 private:
+  bool myBoolean;
   std::string myValue;
   ModelHighAPI_Selection mySelection;
   AttributeSelectionPtr mySelectionAttr;
index 8cd8ebeac395554de241a91f057caec26ea666a7..301f5167004789f0f6330fa0e6ab1acab66a52c6 100644 (file)
@@ -37,13 +37,16 @@ FiltersAPI_Feature::~FiltersAPI_Feature()
 
 static void separateArguments(const std::list<FiltersAPI_Argument>& theArguments,
                               std::list<ModelHighAPI_Selection>& theSelections,
-                              std::list<std::string>& theTextArgs)
+                              std::list<std::string>& theTextArgs,
+                              std::list<bool>& theBoolArgs)
 {
   std::list<FiltersAPI_Argument>::const_iterator anIt = theArguments.begin();
   for (; anIt != theArguments.end(); ++anIt) {
     if (anIt->selection().variantType() != ModelHighAPI_Selection::VT_Empty)
       theSelections.push_back(anIt->selection());
-    else if (!anIt->string().empty())
+    else if (anIt->string().empty())
+      theBoolArgs.push_back(anIt->boolean());
+    else
       theTextArgs.push_back(anIt->string());
   }
 }
@@ -61,12 +64,18 @@ void FiltersAPI_Feature::setFilters(const std::list<FilterAPIPtr>& theFilters)
       // separate selection arguments and strings
       std::list<ModelHighAPI_Selection> aSelections;
       std::list<std::string> aTexts;
-      separateArguments(anArgs, aSelections, aTexts);
+      std::list<bool> aBools;
+      separateArguments(anArgs, aSelections, aTexts, aBools);
 
-      // fill arguments of the filter
       std::list<AttributePtr> aFilterArgs = aBase->filterArgs((*anIt)->name());
-      for (std::list<AttributePtr>::iterator aFIt = aFilterArgs.begin();
-           aFIt != aFilterArgs.end(); ++aFIt) {
+      std::list<AttributePtr>::iterator aFIt = aFilterArgs.begin();
+      // first boolean argument is always "Reversed" flag
+      AttributeBooleanPtr aReversedFlag =
+          std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(*aFIt);
+      if (aReversedFlag)
+        ++aFIt;
+      // fill arguments of the filter
+      for (; aFIt != aFilterArgs.end(); ++aFIt) {
         AttributeSelectionListPtr aSelList =
             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aFIt);
         if (aSelList)
@@ -79,8 +88,16 @@ void FiltersAPI_Feature::setFilters(const std::list<FilterAPIPtr>& theFilters)
           else {
             AttributeStringPtr aString =
                 std::dynamic_pointer_cast<ModelAPI_AttributeString>(*aFIt);
-            if (aString && aTexts.size() == 1)
-              fillAttribute(aTexts.front(), aString);
+            if (aString) {
+              if (aTexts.size() == 1)
+                fillAttribute(aTexts.front(), aString);
+            }
+            else {
+              AttributeBooleanPtr aBoolean =
+                  std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(*aFIt);
+              if (aBoolean && aBools.size() == 1)
+                fillAttribute(aBools.front(), aBoolean);
+            }
           }
         }
       }
index 0e799e49eab87a8f725b29983f5bb5d960c1dacf..c39d0c7caca0577a938cd4ae065b3df47621ae98 100644 (file)
@@ -70,6 +70,12 @@ FiltersAPI_Filter::FiltersAPI_Filter(const std::string& theName,
       myFilterArguments.push_back(FiltersAPI_Argument(aString->value()));
       continue;
     }
+
+    AttributeBooleanPtr aBoolean = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(*anArgIt);
+    if (aBoolean) {
+      myFilterArguments.push_back(FiltersAPI_Argument(aBoolean->value()));
+      continue;
+    }
   }
 }
 
index bc9646cee8db95d21b15c9ebdfba62a1ee234c66..7c1e0ef4da2d1bebe1e81a692b98206d4631586f 100644 (file)
@@ -59,6 +59,10 @@ SET(PROJECT_LIBRARIES
     GeomAlgoAPI
 )
 
+SET(PROJECT_PYFILES
+    FiltersPlugin_TopoConnectedFaces.py
+)
+
 SET(XML_RESOURCES
   plugin-Filters.xml
   filter-BelongsTo.xml
@@ -68,6 +72,7 @@ SET(XML_RESOURCES
   filter-OnPlaneSide.xml
   filter-OppositeToEdge.xml
   filter-RelativeToSolid.xml
+  filter-TopoConnectedFaces.xml
 )
 
 ADD_DEFINITIONS(-DFILTERS_EXPORTS ${OpenCASCADE_DEFINITIONS})
@@ -86,6 +91,8 @@ INCLUDE_DIRECTORIES(
 
 INSTALL(TARGETS Filters DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
 INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+INSTALL(FILES ${PROJECT_PYFILES} DESTINATION ${SHAPER_INSTALL_ADDONS})
+
 
 ADD_UNIT_TESTS(
   TestFilters.py
@@ -106,4 +113,22 @@ ADD_UNIT_TESTS(
   TestFilter_ExternalFaces.py
   TestFilter_HorizontalFaces.py
   TestFilter_VerticalFaces.py
+  TestFilter_TopoConnectedFaces_Vertex1.py
+  TestFilter_TopoConnectedFaces_Vertex2.py
+  TestFilter_TopoConnectedFaces_Vertex3.py
+  TestFilter_TopoConnectedFaces_Prop_Vertex1.py
+  TestFilter_TopoConnectedFaces_Prop_Vertex2.py
+  TestFilter_TopoConnectedFaces_Prop_Vertex3.py
+  TestFilter_TopoConnectedFaces_Edge1.py
+  TestFilter_TopoConnectedFaces_Edge2.py
+  TestFilter_TopoConnectedFaces_Edge3.py
+  TestFilter_TopoConnectedFaces_Prop_Edge1.py
+  TestFilter_TopoConnectedFaces_Prop_Edge2.py
+  TestFilter_TopoConnectedFaces_Prop_Edge3.py
+  TestFilter_TopoConnectedFaces_Face1.py
+  TestFilter_TopoConnectedFaces_Face2.py
+  TestFilter_TopoConnectedFaces_Face3.py
+  TestFilter_TopoConnectedFaces_Prop_Face1.py
+  TestFilter_TopoConnectedFaces_Prop_Face2.py
+  TestFilter_TopoConnectedFaces_Prop_Face3.py
 )
index 2538b8f26939c4e195e21be9bb81184ec84b9358..0ff5b5f69386d11988ddec1e2fc121663e3b6f04 100644 (file)
@@ -30,6 +30,8 @@
 #include "FiltersPlugin_RelativeToSolid.h"
 #include "FiltersPlugin_ExternalFaces.h"
 
+#include <Config_ModuleReader.h>
+
 #include <ModelAPI_Session.h>
 #include <ModelAPI_FiltersFactory.h>
 
@@ -52,6 +54,8 @@ FiltersPlugin_Plugin::FiltersPlugin_Plugin()
   aFactory->registerFilter("RelativeToSolid", new FiltersPlugin_RelativeToSolid);
   aFactory->registerFilter("ExternalFaces", new FiltersPlugin_ExternalFaces);
 
+  Config_ModuleReader::loadScript("FiltersPlugin_TopoConnectedFaces");
+
   ModelAPI_Session::get()->registerPlugin(this);
 }
 
diff --git a/src/FiltersPlugin/FiltersPlugin_TopoConnectedFaces.py b/src/FiltersPlugin/FiltersPlugin_TopoConnectedFaces.py
new file mode 100644 (file)
index 0000000..7176e34
--- /dev/null
@@ -0,0 +1,119 @@
+# 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 ModelAPI import *
+from GeomAPI import *
+from GeomAlgoAPI import GeomAlgoAPI_MapShapesAndAncestors as mapShapesAndAncestors
+
+FILTER_ID = "TopoConnectedFaces"
+
+def singleton(cls):
+  instance = cls()
+  instance.__call__ = lambda: instance
+  return instance
+
+@singleton
+class FiltersPlugin_TopoConnectedFaces(ModelAPI_Filter):
+  """
+  Filter for faces topologically connected to the selected object.
+  """
+
+  def __init__(self):
+    """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+    ModelAPI_Filter.__init__(self)
+    self.myCached = {}
+
+  def name(self):
+    """ Description of the filter """
+    return "Topologically connected faces"
+
+  def isSupported(self, theType):
+    """ Supported types of filtered shapes """
+    return theType == GeomAPI_Shape.FACE
+
+  def isOk(self, theShape, theResult, theArgs):
+    """ True if theShape is applicable for the filter """
+    selectedShapeAttr = modelAPI_AttributeSelection(theArgs.argument("Shape"))
+    if selectedShapeAttr is None:
+      return False
+    selectedShape = selectedShapeAttr.value()
+    isPropagated = modelAPI_AttributeBoolean(theArgs.argument("Propagation")).value()
+
+    # cache selected shape and applicable faces
+    if selectedShape not in self.myCached:
+      anOwner = bodyOwner(theResult, True)
+      if anOwner is None:
+        anOwner = modelAPI_ResultBody(theResult)
+        if anOwner is None:
+          return False
+      topLevelShape = anOwner.shape()
+      mapVFAlgo = mapShapesAndAncestors(topLevelShape, GeomAPI_Shape.VERTEX, GeomAPI_Shape.FACE)
+      mapVF = mapVFAlgo.map()
+      mapEFAlgo = mapShapesAndAncestors(topLevelShape, GeomAPI_Shape.EDGE, GeomAPI_Shape.FACE)
+      mapEF = mapEFAlgo.map()
+
+      # faces adjacent to the selected shape
+      applicableFaces = OriShapeSet()
+      if selectedShape.shapeType() == GeomAPI_Shape.VERTEX:
+        if selectedShape in mapVF: applicableFaces = mapVF[selectedShape]
+      elif selectedShape.shapeType() == GeomAPI_Shape.EDGE:
+        if selectedShape in mapEF: applicableFaces = mapEF[selectedShape]
+      elif selectedShape.shapeType() == GeomAPI_Shape.FACE:
+        applicableFaces.insert(selectedShape)
+        self.adjacentFaces(selectedShape, mapVF, GeomAPI_Shape.VERTEX, applicableFaces, False)
+      else:
+        return False
+      # propagate the connection
+      if isPropagated:
+        appFacesCopy = applicableFaces
+        for ind in range(appFacesCopy.size()):
+          self.adjacentFaces(appFacesCopy[ind], mapEF, GeomAPI_Shape.EDGE, applicableFaces)
+      self.myCached[selectedShape] = applicableFaces
+
+    return theShape in self.myCached[selectedShape]
+
+  def xmlRepresentation(self):
+    """ Returns XML string which represents GUI of the filter """
+    return self.xmlFromFile("filter-TopoConnectedFaces.xml")
+
+  def initAttributes(self, theArgs):
+    """ Initializes arguments of a filter """
+    theArgs.initAttribute("Shape", ModelAPI_AttributeSelection_typeId())
+    theArgs.initAttribute("Propagation", ModelAPI_AttributeBoolean_typeId())
+
+  def adjacentFaces(self, theFace, theMapSA, theShapeType, theApplicableFaces, theRecursive = True):
+    """ Find all faces neighbour to theFace """
+    exp = GeomAPI_ShapeExplorer(theFace, theShapeType)
+    while exp.more():
+      if  exp.current() in theMapSA:
+        faces = theMapSA[exp.current()]
+        for ind in range(faces.size()):
+          f = faces[ind]
+          if f not in theApplicableFaces:
+            theApplicableFaces.insert(f)
+            if theRecursive:
+              self.adjacentFaces(f, theMapSA, theShapeType, theApplicableFaces)
+      exp.next()
+
+
+# Register the filter object
+filter = FiltersPlugin_TopoConnectedFaces
+aSession = ModelAPI_Session.get()
+aSession.filters().registerFilter(FILTER_ID, filter)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge1.py
new file mode 100644 (file)
index 0000000..a53fc56
--- /dev/null
@@ -0,0 +1,72 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge2.py
new file mode 100644 (file)
index 0000000..09818ac
--- /dev/null
@@ -0,0 +1,75 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True; exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Edge3.py
new file mode 100644 (file)
index 0000000..c9b8f6b
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "([Cylinder_1_1/Face_1][Cylinder_1_1/Face_2])([Cylinder_1_1/Face_1][Cylinder_1_1/Face_3])"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultCylinder_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultCylinder_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultCylinder_1, exp.current())] = False; exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face1.py
new file mode 100644 (file)
index 0000000..edcc01e
--- /dev/null
@@ -0,0 +1,75 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Left"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face2.py
new file mode 100644 (file)
index 0000000..7ec4230
--- /dev/null
@@ -0,0 +1,81 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Face3.py
new file mode 100644 (file)
index 0000000..cd09cc0
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Cylinder_1_1/Face_3"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultCylinder_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultCylinder_1, exp.current())] = False; exp.next()
+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_TopoConnectedFaces_Prop_Edge1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge1.py
new file mode 100644 (file)
index 0000000..1ebc101
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "[Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge2.py
new file mode 100644 (file)
index 0000000..d4914af
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "Partition_1_1_2/Generated_Edge&Plane_2/Plane_2&Box_1_1/Top"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Edge3.py
new file mode 100644 (file)
index 0000000..3f6605d
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("EDGE", "([Cylinder_1_1/Face_1][Cylinder_1_1/Face_2])([Cylinder_1_1/Face_1][Cylinder_1_1/Face_3])"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_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()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face1.py
new file mode 100644 (file)
index 0000000..01d2ab7
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Partition_1_1_3/Modified_Face&Box_1_1/Left"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face2.py
new file mode 100644 (file)
index 0000000..dda94d3
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Partition_1_1_2/Modified_Face&Box_1_1/Top"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Face3.py
new file mode 100644 (file)
index 0000000..29fb41d
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("FACE", "Cylinder_1_1/Face_3"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_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()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex1.py
new file mode 100644 (file)
index 0000000..340f243
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex2.py
new file mode 100644 (file)
index 0000000..6d51a55
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = True
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = True
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = True
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = True
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Prop_Vertex3.py
new file mode 100644 (file)
index 0000000..ca73b31
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Cylinder_1_1/Face_1][Cylinder_1_1/Face_3]"), True])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_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()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex1.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex1.py
new file mode 100644 (file)
index 0000000..2f2dafb
--- /dev/null
@@ -0,0 +1,72 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Top][Partition_1_1_3/Modified_Face&Box_1_1/Front][Partition_1_1_3/Modified_Face&Box_1_1/Left]"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex2.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex2.py
new file mode 100644 (file)
index 0000000..01d9f9c
--- /dev/null
@@ -0,0 +1,81 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Top][Partition_1_1_2/Modified_Face&Plane_1/Plane_1][Partition_1_1_2/Modified_Face&Plane_2/Plane_2]"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_0, exp.current())] = True;  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_1, exp.current())] = True;  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_2, exp.current())] = False; exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultBox_3, exp.current())] = False; exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultCylinder_1, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex3.py b/src/FiltersPlugin/Test/TestFilter_TopoConnectedFaces_Vertex3.py
new file mode 100644 (file)
index 0000000..7727e75
--- /dev/null
@@ -0,0 +1,69 @@
+# 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)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Right"))
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("FACE", "Box_1_1/Back"))
+Partition_1_objects = [model.selection("SOLID", "Box_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "TopoConnectedFaces", args = [model.selection("VERTEX", "[Cylinder_1_1/Face_1][Cylinder_1_1/Face_3]"), False])])
+model.end()
+
+Reference = {}
+# Faces of the box
+ResultBox_0 = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_0.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_0, exp.current())] = False
+  exp.next()
+
+ResultBox_1 = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_1, exp.current())] = False
+  exp.next()
+
+ResultBox_2 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_2, exp.current())] = False
+  exp.next()
+
+ResultBox_3 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_3.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResultBox_3, exp.current())] = False
+  exp.next()
+
+# Faces of the cylinder
+ResultCylinder_1 = Cylinder_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultCylinder_1.shape(), GeomAPI_Shape.FACE)
+Reference[model.selection(ResultCylinder_1, exp.current())] = True;  exp.next()
+Reference[model.selection(ResultCylinder_1, exp.current())] = False; exp.next()
+Reference[model.selection(ResultCylinder_1, exp.current())] = True;  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
diff --git a/src/FiltersPlugin/filter-TopoConnectedFaces.xml b/src/FiltersPlugin/filter-TopoConnectedFaces.xml
new file mode 100644 (file)
index 0000000..ebc90b8
--- /dev/null
@@ -0,0 +1,9 @@
+<filter id="TopoConnectedFaces">
+  <shape_selector id="TopoConnectedFaces__Shape"
+                  label="Shape:"
+                  tooltip="Select vertex, edge or face."
+                  shape_types="vertex edge face">
+    <validator id="GeomValidators_ShapeType" parameters="vertex,edge,face"/>
+  </shape_selector>
+  <boolvalue id="TopoConnectedFaces__Propagation" label="Propagation"/>
+</filter>
index 061eedfed7d877577bcfbcac4485d4724d4b2ca3..56ab015a7362fe37d094886783b38a1164553c7c 100644 (file)
 // standard definitions
 %include "typemaps.i"
 %include "std_list.i"
-%include "std_string.i"
+%include "std_map.i"
+%include "std_set.i"
 %include "std_shared_ptr.i"
+%include "std_string.i"
 
 // shared pointers
 %shared_ptr(GeomAPI_AISObject)
 // std::list -> []
 %template(PointList) std::list<std::shared_ptr<GeomAPI_Pnt> >;
 %template(ShapeList) std::list<std::shared_ptr<GeomAPI_Shape> >;
+// std::set -> []
+%template(ShapeSet) std::set<std::shared_ptr<GeomAPI_Shape>, GeomAPI_Shape::Comparator>;
+%template(OriShapeSet) std::set<std::shared_ptr<GeomAPI_Shape>, GeomAPI_Shape::ComparatorWithOri>;
+// std::map -> {}
+%template(ShapeToShapesMap) std::map<std::shared_ptr<GeomAPI_Shape>, std::set<std::shared_ptr<GeomAPI_Shape>, GeomAPI_Shape::ComparatorWithOri>, GeomAPI_Shape::Comparator>;
index 011aa3dd435edb34a2ccd60f01db05468a749070..634cd575d886538ae7150b59ad4117473c415848 100644 (file)
@@ -720,3 +720,14 @@ bool GeomAPI_Shape::Comparator::operator()(const std::shared_ptr<GeomAPI_Shape>&
 {
   return theShape1->impl<TopoDS_Shape>().TShape() < theShape2->impl<TopoDS_Shape>().TShape();
 }
+
+bool GeomAPI_Shape::ComparatorWithOri::operator()(
+    const std::shared_ptr<GeomAPI_Shape>& theShape1,
+    const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+  return (aShape1.TShape() < aShape2.TShape()) ||
+         (aShape1.TShape() == aShape2.TShape() &&
+          aShape1.Orientation() < aShape2.Orientation());
+}
index ab0166bfb62023385b19dbd02f3c234061a162b8..2202d022664622308452afc0ec41863a2f40dfab 100644 (file)
@@ -224,6 +224,7 @@ public:
   GEOMAPI_EXPORT bool isSelfIntersected(const int theLevelOfCheck = 9) const;
 
 public:
+  /// \brief Compare addresses of shapes
   class Comparator
   {
   public:
@@ -232,6 +233,17 @@ public:
     bool operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
                      const std::shared_ptr<GeomAPI_Shape>& theShape2) const;
   };
+
+  /// \brief Compare addresses of shapes with respect to orientation of shapes.
+  ///        Same TShapes with opposite orientations will be treated as different.
+  class ComparatorWithOri
+  {
+  public:
+    /// Return \c true if the address of the first shape is less than the address of the second
+    GEOMAPI_EXPORT
+      bool operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+                       const std::shared_ptr<GeomAPI_Shape>& theShape2) const;
+  };
 };
 
 //! Pointer on list of shapes
index 49734838f7897b8faf3fc6959051c7d3daa31362..6e09db85a3fe8abd9ae5b4d26420949266df26be 100644 (file)
@@ -80,6 +80,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_NExplode.h
     GeomAlgoAPI_Offset.h
     GeomAlgoAPI_SolidClassifier.h
+    GeomAlgoAPI_MapShapesAndAncestors.h
 )
 
 SET(PROJECT_SOURCES
@@ -139,6 +140,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_NExplode.cpp
     GeomAlgoAPI_Offset.cpp
     GeomAlgoAPI_SolidClassifier.cpp
+    GeomAlgoAPI_MapShapesAndAncestors.cpp
 )
 
 SET(PROJECT_LIBRARIES
index d1c014e1b6d0783a541d7fc46f32425296787b87..f2076869f927d0f9ab971aaf053d2a104d36d0cd 100644 (file)
@@ -57,6 +57,7 @@
 %shared_ptr(GeomAlgoAPI_ConeSegment)
 %shared_ptr(GeomAlgoAPI_Copy)
 %shared_ptr(GeomAlgoAPI_Symmetry)
+%shared_ptr(GeomAlgoAPI_MapShapesAndAncestors)
 
 // all supported interfaces
 %include "GeomAlgoAPI_MakeShape.h"
@@ -97,6 +98,7 @@
 %include "GeomAlgoAPI_Copy.h"
 %include "GeomAlgoAPI_Symmetry.h"
 %include "GeomAlgoAPI_Box.h"
+%include "GeomAlgoAPI_MapShapesAndAncestors.h"
 
 %typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & {
   $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr<GeomAPI_Shape>(*$1)), $descriptor(std::shared_ptr<GeomAPI_Shape> *), SWIG_POINTER_OWN | 0 );
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.cpp
new file mode 100644 (file)
index 0000000..3a7985c
--- /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
+//
+
+#include "GeomAlgoAPI_MapShapesAndAncestors.h"
+
+#include <GeomAPI_ShapeExplorer.h>
+
+GeomAlgoAPI_MapShapesAndAncestors::GeomAlgoAPI_MapShapesAndAncestors(
+    const std::shared_ptr<GeomAPI_Shape> theShape,
+    const GeomAPI_Shape::ShapeType theShapeType,
+    const GeomAPI_Shape::ShapeType theAncestorType)
+{
+  perform(theShape, theShapeType, theAncestorType);
+}
+
+void GeomAlgoAPI_MapShapesAndAncestors::perform(
+    const std::shared_ptr<GeomAPI_Shape> theShape,
+    const GeomAPI_Shape::ShapeType theShapeType,
+    const GeomAPI_Shape::ShapeType theAncestorType)
+{
+  myMap.clear();
+
+  GeomAPI_ShapeExplorer anAncIt(theShape, theAncestorType);
+  for (; anAncIt.more(); anAncIt.next()) {
+    GeomAPI_ShapeExplorer aShIt(anAncIt.current(), theShapeType);
+    for (; aShIt.more(); aShIt.next())
+      myMap[aShIt.current()].insert(anAncIt.current());
+  }
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.h b/src/GeomAlgoAPI/GeomAlgoAPI_MapShapesAndAncestors.h
new file mode 100644 (file)
index 0000000..72a7336
--- /dev/null
@@ -0,0 +1,57 @@
+// 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 GeomAlgoAPI_MapShapesAndAncestors_H_
+#define GeomAlgoAPI_MapShapesAndAncestors_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <GeomAPI_Shape.h>
+
+#include <map>
+#include <set>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShapes;
+typedef std::map<GeomShapePtr, SetOfShapes, GeomAPI_Shape::Comparator> MapShapeToShapes;
+
+/// \class GeomAlgoAPI_MapShapesAndAncestors
+/// \ingroup DataAlgo
+/// \brief Perform mapping specified types of sub-shapes of given shape
+class GeomAlgoAPI_MapShapesAndAncestors
+{
+public:
+  /// \brief Perform mapping.
+  GEOMALGOAPI_EXPORT
+  GeomAlgoAPI_MapShapesAndAncestors(const std::shared_ptr<GeomAPI_Shape> theShape,
+                                    const GeomAPI_Shape::ShapeType theShapeType,
+                                    const GeomAPI_Shape::ShapeType theAncestorType);
+  /// \brief Perform mapping.
+  GEOMALGOAPI_EXPORT
+  void perform(const std::shared_ptr<GeomAPI_Shape> theShape,
+               const GeomAPI_Shape::ShapeType theShapeType,
+               const GeomAPI_Shape::ShapeType theAncestorType);
+
+  /// \return Map of sub-shapes.
+  const MapShapeToShapes& map() const { return myMap; }
+
+private:
+  MapShapeToShapes myMap;
+};
+
+#endif
index 91970e2ec4ebed95d7c5bcd51967b48a57677f56..d5b35462e3a3d0f188cc4c0e8e189cdf58ab5864 100644 (file)
@@ -62,6 +62,7 @@
   #include "GeomAlgoAPI_ConeSegment.h"
   #include "GeomAlgoAPI_Copy.h"
   #include "GeomAlgoAPI_Symmetry.h"
+  #include "GeomAlgoAPI_MapShapesAndAncestors.h"
 
   #include <memory>
   #include <string>
index 5050456495a826d303854bc811c4d1f239a09ee5..6f6a1f784d7dd4c7467105adc9f43c87b7a56916 100644 (file)
@@ -54,6 +54,7 @@
 %feature("director") ModelAPI_CompositeFeature;
 %feature("director") ModelAPI_Data;
 %feature("director") ModelAPI_Folder;
+%feature("director") ModelAPI_Filter;
 
 // shared pointers
 // For ModelAPI_ResultConstruction.shape()
index 05b85f6b60a033ddc5bce267afd02294b1901f4b..4adeec43261d103ce4a0d486916ed2b1781f6145 100644 (file)
@@ -33,6 +33,8 @@
 class ModelAPI_Filter
 {
 public:
+  virtual ~ModelAPI_Filter() {}
+
   /// Returns name of the filter to represent it in GUI
   virtual const std::string& name() const = 0;
 
@@ -56,10 +58,9 @@ public:
   /// not redefined.
   virtual void initAttributes(ModelAPI_FiltersArgs& theArguments) {}
 
-protected:
   /// Returns XML string which represents GUI of the filter
   /// by reading corresponding XML file.
-  MODELAPI_EXPORT std::string xmlFromFile(const std::string& theConfigFile) const;
+  MODELAPI_EXPORT virtual std::string xmlFromFile(const std::string& theConfigFile) const;
 
 private:
   bool myIsReverse;