Salome HOME
Implement filter "F3: On a Line"
authorazv <azv@opencascade.com>
Mon, 24 Jun 2019 14:25:52 +0000 (17:25 +0300)
committerazv <azv@opencascade.com>
Mon, 24 Jun 2019 14:25:52 +0000 (17:25 +0300)
src/FiltersPlugin/CMakeLists.txt
src/FiltersPlugin/FiltersPlugin_OnLine.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_OnLine.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Plugin.cpp
src/FiltersPlugin/Test/TestFilter_OnLine.py [new file with mode: 0644]

index 4ff7f61f2a009ce5ced1ea38061920d03db55bad..26b732a55d92b2001781f936196f81492b581877 100644 (file)
@@ -28,6 +28,7 @@ SET(PROJECT_HEADERS
     FiltersPlugin_VerticalFace.h
     FiltersPlugin_BelongsTo.h
     FiltersPlugin_OnPlane.h
+    FiltersPlugin_OnLine.h
 )
 
 SET(PROJECT_SOURCES
@@ -37,6 +38,7 @@ SET(PROJECT_SOURCES
     FiltersPlugin_VerticalFace.cpp
     FiltersPlugin_BelongsTo.cpp
     FiltersPlugin_OnPlane.cpp
+    FiltersPlugin_OnLine.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -70,6 +72,7 @@ ADD_UNIT_TESTS(
   TestFilters.py
   TestFilter_BelongsTo.py
   TestFilter_OnPlane.py
+  TestFilter_OnLine.py
   TestFilter_HorizontalFaces.py
   TestFilter_VerticalFaces.py
 )
diff --git a/src/FiltersPlugin/FiltersPlugin_OnLine.cpp b/src/FiltersPlugin/FiltersPlugin_OnLine.cpp
new file mode 100644 (file)
index 0000000..092321e
--- /dev/null
@@ -0,0 +1,101 @@
+// 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 "FiltersPlugin_OnLine.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Vertex.h>
+
+
+static void convertToLines(const AttributeSelectionListPtr& theSelected,
+                           std::list<GeomLinePtr>& theLines)
+{
+  for (int i = 0; i < theSelected->size(); i++) {
+    GeomShapePtr aCurShape = theSelected->value(i)->value();
+    if (aCurShape && aCurShape->isEdge()) {
+      GeomLinePtr aLine = aCurShape->edge()->line();
+      if (aLine)
+        theLines.push_back(aLine);
+    }
+  }
+}
+
+
+bool FiltersPlugin_OnLine::isSupported(GeomAPI_Shape::ShapeType theType) const
+{
+  return theType == GeomAPI_Shape::EDGE || theType == GeomAPI_Shape::VERTEX;
+}
+
+bool FiltersPlugin_OnLine::isOk(const GeomShapePtr& theShape,
+                                const ModelAPI_FiltersArgs& theArgs) const
+{
+  AttributePtr aAttr = theArgs.argument("OnLine");
+  AttributeSelectionListPtr aList =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
+  if (!aList.get())
+    return false;
+  // convert selected shapes to lines
+  std::list<GeomLinePtr> aLines;
+  convertToLines(aList, aLines);
+
+  if (theShape->isVertex()) {
+    GeomPointPtr aPnt = theShape->vertex()->point();
+    for (std::list<GeomLinePtr>::iterator anIt = aLines.begin(); anIt != aLines.end(); ++anIt) {
+      if ((*anIt)->contains(aPnt))
+        return true;
+    }
+  }
+  else if (theShape->isEdge()) {
+    GeomEdgePtr aEdge(new GeomAPI_Edge(theShape));
+    if (aEdge->isLine()) {
+      GeomPointPtr aPnt1 = aEdge->firstPoint();
+      GeomPointPtr aPnt2 = aEdge->lastPoint();
+      for (std::list<GeomLinePtr>::iterator anIt = aLines.begin(); anIt != aLines.end(); ++anIt) {
+        if ((*anIt)->contains(aPnt1) && (*anIt)->contains(aPnt2))
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+static std::string XMLRepresentation =
+"<filter id = \"OnLine\">"
+" <multi_selector id=\"OnLine__OnLine\""
+"   label=\"Lines:\""
+"   tooltip=\"Select vertices or segments.\""
+"   type_choice=\"edges\">"
+"   <validator id=\"GeomValidators_ShapeType\" parameters=\"line\"/>"
+" </multi_selector>"
+"</filter>";
+
+
+std::string FiltersPlugin_OnLine::xmlRepresentation() const
+{
+  return XMLRepresentation;
+}
+
+void FiltersPlugin_OnLine::initAttributes(ModelAPI_FiltersArgs& theArguments)
+{
+  theArguments.initAttribute("OnLine", ModelAPI_AttributeSelectionList::typeId());
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_OnLine.h b/src/FiltersPlugin/FiltersPlugin_OnLine.h
new file mode 100644 (file)
index 0000000..8678159
--- /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 FILTERSPLUGIN_ONLINE_H_
+#define FILTERSPLUGIN_ONLINE_H_
+
+#include "FiltersPlugin.h"
+
+#include <ModelAPI_Filter.h>
+
+/**\class FiltersPlugin_OnLine
+* \ingroup DataModel
+* \brief Filter for objects which belong to selected lines
+*/
+class FiltersPlugin_OnLine : public ModelAPI_Filter
+{
+public:
+  FiltersPlugin_OnLine() : ModelAPI_Filter() {}
+
+  virtual const std::string& name() const {
+    static const std::string kName("On line");
+    return kName;
+  }
+
+  /// Returns true for any type because it supports all selection types
+  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
+  virtual bool isOk(const GeomShapePtr& theShape,
+                    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
\ No newline at end of file
index 6f0b9886c0c78726d70f453af037d4a599b3dc47..d35bf7f40ce557a4c0fa529f35b8d7cdb994c280 100644 (file)
@@ -23,6 +23,7 @@
 #include "FiltersPlugin_VerticalFace.h"
 #include "FiltersPlugin_BelongsTo.h"
 #include "FiltersPlugin_OnPlane.h"
+#include "FiltersPlugin_OnLine.h"
 
 #include <ModelAPI_Session.h>
 #include <ModelAPI_FiltersFactory.h>
@@ -39,6 +40,7 @@ FiltersPlugin_Plugin::FiltersPlugin_Plugin()
   aFactory->registerFilter("VerticalFaces", new FiltersPlugin_VerticalFace);
   aFactory->registerFilter("BelongsTo", new FiltersPlugin_BelongsTo);
   aFactory->registerFilter("OnPlane", new FiltersPlugin_OnPlane);
+  aFactory->registerFilter("OnLine", new FiltersPlugin_OnLine);
 
   ModelAPI_Session::get()->registerPlugin(this);
 }
diff --git a/src/FiltersPlugin/Test/TestFilter_OnLine.py b/src/FiltersPlugin/Test/TestFilter_OnLine.py
new file mode 100644 (file)
index 0000000..3400096
--- /dev/null
@@ -0,0 +1,93 @@
+# Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 20, 2, model.selection("EDGE", "PartSet/OY"), 20, 3)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OnLine", args = [model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"), model.selection("EDGE", "[LinearCopy_1_1_4/MF:Translated&Box_1_1/Front][LinearCopy_1_1_4/MF:Translated&Box_1_1/Top]")])])
+model.end()
+
+Reference = {
+    # Faces are not supported
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Top"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Front"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Back"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Right"): False,
+    model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Box_1_1/Left"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"): False,
+    model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_3"): False,
+    # Edges of the original box
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    # Edges of translated box
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Left][LinearCopy_1_1_2/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Right][LinearCopy_1_1_2/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated&Box_1_1/Left]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated&Box_1_1/Right]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Left][LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Right][LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Front][LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("EDGE", "[LinearCopy_1_1_2/MF:Translated&Box_1_1/Back][LinearCopy_1_1_2/MF:Translated&Box_1_1/Bottom]"): False,
+    # Edges of the cylinder
+    model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"): False,
+    model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_3]"): False,
+    model.selection("EDGE", "([Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2])([Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_3])"): False,
+    # Vertices of the original box
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): True,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Back][LinearCopy_1_1_1/MF:Translated&Box_1_1/Left][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_1/MF:Translated&Box_1_1/Front][LinearCopy_1_1_1/MF:Translated&Box_1_1/Right][LinearCopy_1_1_1/MF:Translated&Box_1_1/Bottom]"): False,
+    # Vertices of translated box
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Top]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Left][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Front][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    model.selection("VERTEX", "[LinearCopy_1_1_5/MF:Translated&Box_1_1/Back][LinearCopy_1_1_5/MF:Translated&Box_1_1/Right][LinearCopy_1_1_5/MF:Translated&Box_1_1/Bottom]"): False,
+    }
+model.checkFilter(Part_1_doc, model, Filters, Reference)