Salome HOME
[EDF] (2023-T1) Filters on group 35157_FiltersOnGroup 27/head
authorEkaterina Sukhareva <ekaterina.sukhareva@opencascade.com>
Fri, 27 Oct 2023 12:14:33 +0000 (13:14 +0100)
committerEkaterina Sukhareva <ekaterina.sukhareva@opencascade.com>
Fri, 10 Nov 2023 12:45:10 +0000 (12:45 +0000)
15 files changed:
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_OnShapeName.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_OnShapeName.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Plugin.cpp
src/FiltersPlugin/FiltersPlugin_msg_en.ts
src/FiltersPlugin/FiltersPlugin_msg_fr.ts
src/FiltersPlugin/Test/TestFilter_OnShapeName.py [new file with mode: 0644]
src/FiltersPlugin/Test/TestFilters_Supported.py
src/FiltersPlugin/doc/FiltersPlugin.rst
src/FiltersPlugin/doc/images/selection_byShapeName1.png [new file with mode: 0755]
src/FiltersPlugin/doc/images/selection_byShapeName2.png [new file with mode: 0755]
src/FiltersPlugin/doc/images/selection_byShapeName3.png [new file with mode: 0755]
src/FiltersPlugin/filter-OnShapeName.xml [new file with mode: 0644]
src/FiltersPlugin/tests.set
src/Model/Model_FiltersFactory.cpp

index 81f3846349e562bff4be5f3cf9c6f5018c695502..e27432794e0dc4e7823f5dc73575e91453d1653a 100644 (file)
@@ -40,6 +40,7 @@ SET(PROJECT_HEADERS
     FiltersPlugin_VolumeSize.h
     FiltersPlugin_FeatureEdges.h
     FiltersPlugin_ContinuousFaces.h
+    FiltersPlugin_OnShapeName.h
 )
 
 SET(PROJECT_SOURCES
@@ -61,6 +62,7 @@ SET(PROJECT_SOURCES
     FiltersPlugin_VolumeSize.cpp
     FiltersPlugin_FeatureEdges.cpp
     FiltersPlugin_ContinuousFaces.cpp
+    FiltersPlugin_OnShapeName.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -91,6 +93,7 @@ SET(XML_RESOURCES
   filter-VolumeSize.xml
   filter-FeatureEdges.xml
   filter-ContinuousFaces.xml
+  filter-OnShapeName.xml
 )
 
 SET(TEXT_RESOURCES
@@ -115,6 +118,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
   ${PROJECT_SOURCE_DIR}/src/GeomValidators
   ${PROJECT_SOURCE_DIR}/src/CollectionPlugin
+  ${PROJECT_SOURCE_DIR}/src/Locale
 )
 
 INSTALL(TARGETS FiltersPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
diff --git a/src/FiltersPlugin/FiltersPlugin_OnShapeName.cpp b/src/FiltersPlugin/FiltersPlugin_OnShapeName.cpp
new file mode 100644 (file)
index 0000000..a01d9cb
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-2023  CEA, EDF
+//
+// 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 "FiltersPlugin_OnShapeName.h"
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Tools.h>
+
+#include <Locale_Convert.h>
+#include <regex>
+
+
+bool FiltersPlugin_OnShapeName::isSupported(GeomAPI_Shape::ShapeType /*theType*/) const
+{
+  return true;
+}
+
+//=======================================================================
+bool FiltersPlugin_OnShapeName::isOk(const GeomShapePtr& theShape, const ResultPtr& theResult,
+                                     const ModelAPI_FiltersArgs& theArgs) const
+{
+  if (!theResult)
+    return false;
+
+  AttributePtr anAttr = theArgs.argument("pattern");
+  AttributeStringPtr aValue = std::dynamic_pointer_cast<ModelAPI_AttributeString>(anAttr);
+  if (!aValue || !anAttr->isInitialized())
+    return false;
+
+  std::regex aPattern(aValue->value());
+
+  ResultBodyPtr aBodyRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+
+  for(; aBodyRes.get(); aBodyRes = ModelAPI_Tools::bodyOwner(aBodyRes))
+  {
+    const DataPtr data = aBodyRes->data();
+    if (data.get()) 
+    {
+      const std::string aResName = Locale::Convert::toString(data->name());
+      if(std::regex_search(aResName, aPattern))
+      {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+//=======================================================================
+std::string FiltersPlugin_OnShapeName::xmlRepresentation() const
+{
+  return xmlFromFile("filter-OnShapeName.xml");
+}
+
+//=======================================================================
+void FiltersPlugin_OnShapeName::initAttributes(ModelAPI_FiltersArgs& theArguments)
+{
+  theArguments.initAttribute("pattern", ModelAPI_AttributeString::typeId());
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_OnShapeName.h b/src/FiltersPlugin/FiltersPlugin_OnShapeName.h
new file mode 100644 (file)
index 0000000..85556ae
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2014-2023  CEA, EDF
+//
+// 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 FILTERSPLUGIN_ONSHAPENAME_H_
+#define FILTERSPLUGIN_ONSHAPENAME_H_
+
+#include "FiltersPlugin.h"
+
+#include <ModelAPI_Filter.h>
+
+/**\class FiltersPlugin_OnPlaneSide
+* \ingroup DataModel
+* \brief Filter for objects which lying on the side of selected plane
+*/
+class FiltersPlugin_OnShapeName : public ModelAPI_Filter
+{
+public:
+    FiltersPlugin_OnShapeName() : ModelAPI_Filter() {}
+
+    virtual const std::string& name() const 
+    {
+        static const std::string kName("On shape name");
+        return kName;
+    }
+
+    /// Returns true for face type
+    virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
+
+    /// This method should contain the filter logic. It returns true if the given shape
+    /// is accepted by the filter.
+    /// \param theShape the given shape
+    /// \param theArgs arguments of the filter
+    virtual bool isOk(const GeomShapePtr& theShape,const ResultPtr& theResult,
+                      const ModelAPI_FiltersArgs& theArgs) const override;
+
+    /// Returns XML string which represents GUI of the filter
+    virtual std::string xmlRepresentation() const override;
+
+    /// Initializes arguments of a filter.
+    virtual void initAttributes(ModelAPI_FiltersArgs& theArguments) override;
+};
+
+#endif
index e543fbb7c6518437cebb829e54397c7f1a52b9af..3549a00fa52d93f7217ed9315c8fc82280c12573 100644 (file)
@@ -35,6 +35,7 @@
 #include "FiltersPlugin_Validators.h"
 #include "FiltersPlugin_VerticalFace.h"
 #include "FiltersPlugin_VolumeSize.h"
+#include "FiltersPlugin_OnShapeName.h"
 
 #include <Config_ModuleReader.h>
 
@@ -64,6 +65,7 @@ FiltersPlugin_Plugin::FiltersPlugin_Plugin()
   aFactory->registerFilter("VolumeSize", new FiltersPlugin_VolumeSize);
   aFactory->registerFilter("FeatureEdges", new FiltersPlugin_FeatureEdges);
   aFactory->registerFilter("ContinuousFaces", new FiltersPlugin_ContinuousFaces);
+  aFactory->registerFilter("OnShapeName", new FiltersPlugin_OnShapeName);
 
   Config_ModuleReader::loadScript("FiltersPlugin_TopoConnectedFaces");
 
index e20f87ad1c3117d1632d2bd4ee44b111e3dad1b3..2d24466efa67d478f5e48a18a700cff9453caef1 100644 (file)
       <source>Opposite to an edge</source>
       <translation>Opposite to an edge</translation>
     </message>
+    <message>
+      <source>On shape name</source>
+      <translation>On shape name</translation>
+    </message>
     <message>
       <source>Topologically connected faces</source>
       <translation>Topologically connected faces</translation>
     </message>
   </context>
 
+  <!-- OnShapeName -->
+  <context>
+    <name>OnShapeName</name>
+    <message>
+      <source>Search pattern:</source>
+      <translation>Search pattern:</translation>
+    </message>
+  </context>
+
 </TS>
index eb39232e58d1a8d661d44fe39f90feb78e5251a1..53ab64b01fca996010f36cecc8076e983c4d1e0a 100644 (file)
       <source>Opposite to an edge</source>
       <translation>En face d&apos;un bord</translation>
     </message>
+    <message>
+      <source>On shape name</source>
+      <translation>Sur le nom des shapes</translation>
+    </message>
     <message>
       <source>Topologically connected faces</source>
       <translation>Faces topologiquement connectés</translation>
     </message>
   </context>
 
+  <!-- OnShapeName -->
+  <context>
+    <name>OnShapeName</name>
+    <message>
+      <source>Search pattern:</source>
+      <translation>Modèle de recherche:</translation>
+    </message>
+  </context>
+
 </TS>
diff --git a/src/FiltersPlugin/Test/TestFilter_OnShapeName.py b/src/FiltersPlugin/Test/TestFilter_OnShapeName.py
new file mode 100644 (file)
index 0000000..cf8e542
--- /dev/null
@@ -0,0 +1,304 @@
+# Copyright (C) 2014-2023  CEA, EDF
+#
+# 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
+#
+
+import salome
+
+salome.salome_init()
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "rayon", '10.')
+model.addParameter(Part_1_doc, "hauteur", '2.*rayon')
+
+### Create Sketch
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+
+### Create SketchProjection
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+
+### Create SketchCircle
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+Sketch_1.setRadius(SketchCircle_1.results()[1], "rayon ")
+model.do()
+
+### Create Extrusion
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection(), "hauteur ", "hauteur/4.", "Faces|Wires")
+
+### Create Sketch
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+
+### Create SketchLine
+SketchLine_1 = Sketch_2.addLine(12.5, -12.5, -12.5, -12.5)
+
+### Create SketchProjection
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+
+### Create SketchLine
+SketchLine_2 = Sketch_2.addLine(-12.5, -12.5, -12.5, 12.5)
+
+### Create SketchLine
+SketchLine_3 = Sketch_2.addLine(-12.5, 12.5, 12.5, 12.5)
+
+### Create SketchLine
+SketchLine_4 = Sketch_2.addLine(12.5, 12.5, 12.5, -12.5)
+Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+
+### Create SketchLine
+SketchLine_5 = Sketch_2.addLine(12.5, -12.5, -12.5, 12.5)
+SketchLine_5.setAuxiliary(True)
+
+### Create SketchLine
+SketchLine_6 = Sketch_2.addLine(-12.5, -12.5, 12.5, 12.5)
+SketchLine_6.setAuxiliary(True)
+Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
+Sketch_2.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
+Sketch_2.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
+Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
+Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_5.result())
+Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_6.result())
+Sketch_2.setHorizontal(SketchLine_1.result())
+Sketch_2.setVertical(SketchLine_2.result())
+Sketch_2.setHorizontal(SketchLine_3.result())
+Sketch_2.setVertical(SketchLine_4.result())
+Sketch_2.setLength(SketchLine_3.result(), "2.5*rayon")
+Sketch_2.setEqual(SketchLine_3.result(), SketchLine_2.result())
+model.do()
+
+### Create Extrusion
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_2")], model.selection(), 0, "2.*rayon", "Faces|Wires")
+
+### Create Sketch
+Sketch_3 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+
+### Create SketchLine
+SketchLine_7 = Sketch_3.addLine(-4.930380657631324e-32, -6, -4.930380657631324e-32, 6)
+
+### Create SketchProjection
+SketchProjection_3 = Sketch_3.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_3 = SketchProjection_3.createdFeature()
+Sketch_3.setMiddlePoint(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_7.result())
+Sketch_3.setVertical(SketchLine_7.result())
+Sketch_3.setLength(SketchLine_7.result(), "1.2*rayon")
+model.do()
+
+### Create Extrusion
+Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_3")], model.selection("EDGE", "PartSet/OZ"), "hauteur*1.4", "hauteur*0.4", "Edges")
+
+### Create Extrusion
+Extrusion_4 = model.addExtrusion(Part_1_doc, [model.selection("VERTEX", "PartSet/Origin")], model.selection("EDGE", "PartSet/OY"), "rayon*1.6", "rayon*1.6")
+
+### Create Translation
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "all-in-Extrusion_4")], axis = model.selection("EDGE", "PartSet/OZ"), distance = "hauteur*0.5", keepSubResults = True)
+
+### Create Partition
+Partition_1_objects = [model.selection("COMPOUND", "all-in-Extrusion_1"),
+                       model.selection("COMPOUND", "all-in-Extrusion_2"),
+                       model.selection("COMPOUND", "all-in-Extrusion_3"),
+                       model.selection("COMPOUND", "all-in-Translation_1")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, keepSubResults = True)
+Partition_1.result().subResult(0).setName("Volumes")
+Partition_1.result().subResult(0).subResult(0).setName("Cylindre bas")
+Partition_1.result().subResult(0).subResult(1).setName("Cylindre haut")
+Partition_1.result().subResult(0).subResult(2).setName("Cube Creux")
+Partition_1.result().subResult(1).setName("Plaque")
+Partition_1.result().subResult(2).setName("Poutre 1")
+Partition_1.result().subResult(3).setName("Poutre 2")
+
+model.end()
+model.begin()
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OnShapeName", args = ["Cube"])])
+nFaces = len(Filters.select("FACE"))
+nEdges = len(Filters.select("EDGE"))
+nVerts = len(Filters.select("VERTEX"))
+model.end()
+
+assert nFaces==9, "Wrong number of filtered faces in 1st filter: {}, expected 9".format(nFaces)
+assert nEdges==19, "Wrong number of filtered edges in 1st filter: {}, expected 19".format(nEdges)
+assert nVerts==14, "Wrong number of selected vertexes in 1st filter: {}, expected 14".format(nVerts)
+
+from GeomAPI import *
+
+Reference = {}
+RefCube = Partition_1.result().subResult(0).subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+
+ResfCyl= Partition_1.result().subResult(0).subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = False
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
+
+### ------------------------------------------------------------------------------
+model.begin()
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OnShapeName", args = ["Poutre [0-9]"])])
+nEdges = len(Filters.select("EDGE"))
+nVerts = len(Filters.select("VERTEX"))
+model.end()
+
+assert nEdges==2, "Wrong number of filtered edges in 2d filter: {}, expected 2".format(nEdges)
+assert nVerts==4, "Wrong number of selected vertexes in 2d filter: {}, expected 4".format(nVerts)
+
+Reference = {}
+RefPoutre1 = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(RefPoutre1.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefPoutre1, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefPoutre1.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefPoutre1, exp.current())] = True
+  exp.next()
+RefPoutre2 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(RefPoutre2.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefPoutre2, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefPoutre2.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefPoutre2, exp.current())] = True
+  exp.next()
+
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = False
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
+
+### ------------------------------------------------------------------------------
+model.begin()
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OnShapeName", args = ["Volumes"])])
+nSolids = len(Filters.select("SOLID"))
+nFaces = len(Filters.select("FACE"))
+nEdges = len(Filters.select("EDGE"))
+nVerts = len(Filters.select("VERTEX"))
+model.end()
+
+assert nSolids==3, "Wrong number of filtered solids in 3rd filter: {}, expected 3".format(nSolids)
+assert nFaces==15, "Wrong number of filtered faces in 3rd filter: {}, expected 15".format(nFaces)
+assert nEdges==31, "Wrong number of filtered edges in 3rd filter: {}, expected 31".format(nEdges)
+assert nVerts==19, "Wrong number of selected vertexes in 3rd filter: {}, expected 19".format(nVerts)
+
+Reference = {}
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.SOLID)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefCube.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefCube, exp.current())] = True
+  exp.next()
+
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.SOLID)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResfCyl, exp.current())] = True
+  exp.next()
+
+ResfCyl2= Partition_1.result().subResult(0).subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResfCyl2.shape(), GeomAPI_Shape.SOLID)
+while exp.more():
+  Reference[model.selection(ResfCyl2, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl2.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+  Reference[model.selection(ResfCyl2, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl2.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(ResfCyl2, exp.current())] = True
+  exp.next()
+exp = GeomAPI_ShapeExplorer(ResfCyl2.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(ResfCyl2, exp.current())] = True
+  exp.next()
+
+exp = GeomAPI_ShapeExplorer(RefPoutre1.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefPoutre1, exp.current())] = False
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefPoutre1.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefPoutre1, exp.current())] = False
+  exp.next()
+RefPoutre2 = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(RefPoutre2.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+  Reference[model.selection(RefPoutre2, exp.current())] = False
+  exp.next()
+exp = GeomAPI_ShapeExplorer(RefPoutre2.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+  Reference[model.selection(RefPoutre2, exp.current())] = False
+  exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)
index e6b4934353d308722160bc3daf87366f680df088..a0e033b407069ecc911463c603c43278c06467f6 100644 (file)
@@ -39,15 +39,16 @@ FILTER_FACE_SIZE = "FaceSize"
 FILTER_VOLUME_SIZE = "VolumeSize"
 FILTER_FEATURE_EDGES = "FeatureEdges"
 FILTER_CONTINUOUS_FACES= "ContinuousFaces"
+FILTER_ON_SHAPE_NAME = "OnShapeName"
 
 # Reference data (supported filters) for each type of shape
 Reference = {
-    GeomAPI_Shape.VERTEX : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_LINE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
-    GeomAPI_Shape.EDGE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_LINE, FILTER_ON_GEOMETRY, FILTER_ON_PLANE_SIDE, FILTER_OPPOSITE_TO_EDGE, FILTER_RELATIVE_TO_SOLID, FILTER_EDGE_SIZE, FILTER_FEATURE_EDGES],
-    GeomAPI_Shape.WIRE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
-    GeomAPI_Shape.FACE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_GEOMETRY, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID, FILTER_EXTERNAL_FACES, FILTER_HORIZONTAL_FACES, FILTER_VERTICAL_FACES, FILTER_CONNECTED_FACES, FILTER_FACE_SIZE, FILTER_CONTINUOUS_FACES],
-    GeomAPI_Shape.SHELL  : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID],
-    GeomAPI_Shape.SOLID  : [FILTER_BELONGS_TO, FILTER_ON_PLANE_SIDE, FILTER_VOLUME_SIZE],
+    GeomAPI_Shape.VERTEX : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_LINE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID,FILTER_ON_SHAPE_NAME],
+    GeomAPI_Shape.EDGE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_LINE, FILTER_ON_GEOMETRY, FILTER_ON_PLANE_SIDE, FILTER_OPPOSITE_TO_EDGE, FILTER_RELATIVE_TO_SOLID, FILTER_EDGE_SIZE, FILTER_FEATURE_EDGES,FILTER_ON_SHAPE_NAME],
+    GeomAPI_Shape.WIRE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID,FILTER_ON_SHAPE_NAME],
+    GeomAPI_Shape.FACE   : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_GEOMETRY, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID, FILTER_EXTERNAL_FACES, FILTER_HORIZONTAL_FACES, FILTER_VERTICAL_FACES, FILTER_CONNECTED_FACES, FILTER_FACE_SIZE, FILTER_CONTINUOUS_FACES,FILTER_ON_SHAPE_NAME],
+    GeomAPI_Shape.SHELL  : [FILTER_BELONGS_TO, FILTER_ON_PLANE, FILTER_ON_PLANE_SIDE, FILTER_RELATIVE_TO_SOLID,FILTER_ON_SHAPE_NAME],
+    GeomAPI_Shape.SOLID  : [FILTER_BELONGS_TO, FILTER_ON_PLANE_SIDE, FILTER_VOLUME_SIZE,FILTER_ON_SHAPE_NAME],
 }
 
 model.begin()
index 3d9bbb4920e93119e76e41ea0bcae801fceb07f6..0057248a124bfd8cccf089ab17a1a0298983eb6a 100644 (file)
@@ -179,3 +179,26 @@ This algorithm finds all the faces topologically connected the argument selected
 - **Algorithm:**
     - If a point of an edge is selected as an argument, the result is all faces that contain this argument.If a face is selected, the result is all faces that have shared edges or vertices with this selection.
     - If “propagation” flag is enabled (it is disabled by default), the algorithm becomes recursive: all connected faces are added to the results. So, for the solid shape there will be all faces except internal-volumes faces, not connected to any external faces.
+
+**Shape name**
+
+- **Result type:** Any
+- **Arguments:** A regular expression value, representing a pattern for searching by result name. The search pattern must comply with the rules of regular expressions.
+- **Algorithm:**
+    - Returns objects or subobjects of results where their name matches the given search pattern (regular expression).
+    - For example, if we have in the result a shape with the name “cube” and we want to select all the edges according to the pattern "cube", then we will get all the edges of the objects containing "cube" in their name.
+    - The filter searches not only for complete matches but for any pattern inclusions.
+
+- **Examples:**
+    - Selecting all edges belonging to objects from the result with a name starting with "Cyl".
+    .. figure:: images/selection_byShapeName1.png
+      :align: center
+
+    - Selecting all vertices belonging to objects from the result with a name containing pattern "Cube".
+    .. figure:: images/selection_byShapeName2.png
+      :align: center
+
+    - Selecting all results with names containing "Poutre", followed by a space and a digit.
+    .. figure:: images/selection_byShapeName3.png
+      :align: center
+
diff --git a/src/FiltersPlugin/doc/images/selection_byShapeName1.png b/src/FiltersPlugin/doc/images/selection_byShapeName1.png
new file mode 100755 (executable)
index 0000000..a6241d3
Binary files /dev/null and b/src/FiltersPlugin/doc/images/selection_byShapeName1.png differ
diff --git a/src/FiltersPlugin/doc/images/selection_byShapeName2.png b/src/FiltersPlugin/doc/images/selection_byShapeName2.png
new file mode 100755 (executable)
index 0000000..c51cfe2
Binary files /dev/null and b/src/FiltersPlugin/doc/images/selection_byShapeName2.png differ
diff --git a/src/FiltersPlugin/doc/images/selection_byShapeName3.png b/src/FiltersPlugin/doc/images/selection_byShapeName3.png
new file mode 100755 (executable)
index 0000000..b1fdf28
Binary files /dev/null and b/src/FiltersPlugin/doc/images/selection_byShapeName3.png differ
diff --git a/src/FiltersPlugin/filter-OnShapeName.xml b/src/FiltersPlugin/filter-OnShapeName.xml
new file mode 100644 (file)
index 0000000..bc4770e
--- /dev/null
@@ -0,0 +1,4 @@
+<filter id="OnShapeName">
+  <stringvalue id="OnShapeName__pattern" label="Search pattern:">
+  </stringvalue>
+</filter>
\ No newline at end of file
index f3a894b59c105f96a6aae98d60af5c9e80e7ba96..64a44e684dcacdb0470e9bdd38001c5df2d0932a 100644 (file)
@@ -124,4 +124,5 @@ SET(TEST_NAMES
   TestFilter_FeatureEdges.py
   TestFilter_ContinuousFaces.py
   TestFilter_VolumeSize.py
+  TestFilter_OnShapeName.py
 )
index 005d927ce00b2dba18b51c4a1197fab9f5b9f68f..3e213d04e140ee09f1d91fc040d527b3779ee767 100644 (file)
 
 #include "GeomAPI_Edge.h"
 
+#include <unordered_map>
+#include <stack>
+
+typedef std::unordered_map<GeomShapePtr, ResultBodyPtr,
+                          GeomAPI_Shape::Hash, GeomAPI_Shape::Equal> DataMapOfShapesToResults;
+
 void Model_FiltersFactory::registerFilter(const std::string& theID, ModelAPI_Filter* theFilter)
 {
   if (myFilters.find(theID) != myFilters.end()) {
@@ -56,6 +62,50 @@ static std::string pureFilterID(const std::string& theID)
   return theID;
 }
 
+static void fillMapOfShapesToResults(DataMapOfShapesToResults& theMap,
+                             const ResultBodyPtr& theBodyResult,
+                             const GeomAPI_Shape::ShapeType theShapeType)
+{
+  std::stack<ResultBodyPtr> stack;
+  stack.push(theBodyResult);
+
+  while(!stack.empty())
+  {
+    ResultBodyPtr aCurrBodyRes = stack.top();
+    stack.pop();
+
+    int nbSubs = aCurrBodyRes->numberOfSubs();
+    if(nbSubs == 0)
+    {
+      GeomShapePtr aShape = aCurrBodyRes->shape();
+      std::list<GeomShapePtr> aSubShapes = aShape->subShapes(theShapeType, true);
+      std::list<GeomShapePtr>::const_iterator aShapesIt;
+      for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++)
+      {
+        GeomShapePtr aSubShape = (*aShapesIt);
+
+        // degenerated edge is not valid selection
+        if (theShapeType == GeomAPI_Shape::EDGE)
+          if (aSubShape->edge()->isDegenerated())
+            continue;
+        
+        if (theMap.find(aSubShape) == theMap.end()) 
+        {
+          theMap.emplace(aSubShape, aCurrBodyRes);
+        }
+      }
+    }
+    else
+    {
+        for (int aSubIndex = 0; aSubIndex < nbSubs; aSubIndex++) 
+        {
+          stack.push(aCurrBodyRes->subResult(aSubIndex));
+        }
+    }
+  }
+
+}
+
 bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
                                    ResultPtr theResult,
                                    GeomShapePtr theShape)
@@ -104,6 +154,7 @@ bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature,
   for(; aFilter != aFilters.end(); aFilter++) {
     anArgs.setFilter(aFilter->myFilterID);
     bool aResult = aFilter->myFilter->isOk(theShape, theResult, anArgs);
+
     if (aFilter->myReverse)
       aResult = !aResult;
     if (!aResult) // one filter is failed => exit immediately
@@ -123,46 +174,36 @@ std::list< std::pair<ResultPtr, GeomShapePtr> > Model_FiltersFactory::select
   int aNb = aDoc->size(ModelAPI_ResultBody::group());
   ObjectPtr aObj;
   ResultBodyPtr aBody;
-  for (int i = 0; i < aNb; i++) {
+  for (int i = 0; i < aNb; i++) 
+  {
     aObj = aDoc->object(ModelAPI_ResultBody::group(), i);
     aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObj);
+    DataMapOfShapesToResults aShapeToResMap;
+    fillMapOfShapesToResults(aShapeToResMap, aBody, theShapeType);
+
     GeomShapePtr aShape = aBody->shape();
     std::list<GeomShapePtr> aSubShapes = aShape->subShapes(theShapeType, true);
     std::list<GeomShapePtr>::const_iterator aShapesIt;
-    for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) {
+    for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++)
+    {
       GeomShapePtr aSubShape = (*aShapesIt);
-
       // degenerated edge is not valid selection
       if (theShapeType == GeomAPI_Shape::EDGE)
         if (aSubShape->edge()->isDegenerated())
           continue;
 
-      bool isValid = this->isValid(theFilterFeature, aBody, aSubShape);
-
-      if (isValid) {
-        // bos #24043: Naming on a compsolid works wrong.
-        // Find a simple sub-result for the ViewerPrs context:
-        ResultBodyPtr aContext = aBody;
-        bool isComposite = aContext->numberOfSubs() > 0;
-        while (isComposite) {
-          isComposite = false;
-          int nbSubs = aContext->numberOfSubs();
-          for (int aSubIndex = 0; aSubIndex < nbSubs; aSubIndex++) {
-            ResultBodyPtr aSubResult = aContext->subResult(aSubIndex);
-            GeomShapePtr aSubResultShape = aSubResult->shape();
-            if (aSubResultShape->isSubShape(aSubShape)) {
-              aContext = aSubResult;
-              isComposite = aContext->numberOfSubs() > 0;
-              break;
-            }
-          }
+
+      if (aShapeToResMap.find(aSubShape) != aShapeToResMap.end()) 
+      {
+        ResultBodyPtr aResBody = aShapeToResMap[aSubShape];
+        if(this->isValid(theFilterFeature, aResBody, aSubShape))
+        {
+           std::pair<ResultPtr, GeomShapePtr> aPair(aResBody, aSubShape);
+          aResList.push_back(aPair);
         }
-        std::pair<ResultPtr, GeomShapePtr> aPair (aContext, aSubShape);
-        aResList.push_back(aPair);
       }
     }
   }
-
   return aResList;
 }