From e0cafd4b246880888d085593c52a073f8892e4a2 Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 19 Feb 2020 12:54:17 +0300 Subject: [PATCH] Issue #3141 implementation : Allow usage of the same filters many times --- src/Config/Config_WidgetAPI.cpp | 5 +- src/Config/Config_WidgetAPI.h | 3 +- src/FiltersAPI/FiltersAPI_Feature.cpp | 13 +- src/FiltersPlugin/CMakeLists.txt | 4 + src/FiltersPlugin/FiltersPlugin_OnGeometry.h | 3 - src/FiltersPlugin/FiltersPlugin_OnLine.h | 3 + src/FiltersPlugin/FiltersPlugin_OnPlane.h | 3 + src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h | 3 + .../FiltersPlugin_RelativeToSolid.h | 3 + src/FiltersPlugin/FiltersPlugin_Selection.cpp | 29 +++- src/FiltersPlugin/FiltersPlugin_Selection.h | 3 +- .../Test/TestFilter_OnLine_Multi.py | 46 ++++++ .../Test/TestFilter_OnPlaneSide_Multi.py | 88 +++++++++++ .../Test/TestFilter_OnPlane_Multi.py | 143 ++++++++++++++++++ .../Test/TestFilter_RelativeToSolid_Multi.py | 61 ++++++++ src/FiltersPlugin/doc/FiltersPlugin.rst | 4 +- src/Model/Model_FiltersFactory.cpp | 23 ++- src/ModelAPI/ModelAPI_FiltersFeature.h | 3 +- src/ModuleBase/ModuleBase_WidgetFactory.cpp | 5 +- src/ModuleBase/ModuleBase_WidgetFactory.h | 6 +- .../ModuleBase_WidgetSelectionFilter.cpp | 11 +- 21 files changed, 436 insertions(+), 26 deletions(-) create mode 100644 src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py create mode 100644 src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py create mode 100644 src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py create mode 100644 src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py diff --git a/src/Config/Config_WidgetAPI.cpp b/src/Config/Config_WidgetAPI.cpp index cc1dfa986..5ca092bf8 100644 --- a/src/Config/Config_WidgetAPI.cpp +++ b/src/Config/Config_WidgetAPI.cpp @@ -26,11 +26,12 @@ #include -Config_WidgetAPI::Config_WidgetAPI(std::string theRawXml) +Config_WidgetAPI::Config_WidgetAPI(std::string theRawXml, const std::string theAttributePrefix) { myDoc = xmlParseDoc(BAD_CAST theRawXml.c_str()); myCurrentNode = xmlDocGetRootElement(myDoc); myFeatureId = getProperty(_ID); + myAttributePrefix = theAttributePrefix; } Config_WidgetAPI::~Config_WidgetAPI() @@ -119,7 +120,7 @@ std::string Config_WidgetAPI::featureId() const std::string Config_WidgetAPI::widgetId() const { - return getProperty(_ID); + return myAttributePrefix + getProperty(_ID); } std::string Config_WidgetAPI::widgetIcon() const diff --git a/src/Config/Config_WidgetAPI.h b/src/Config/Config_WidgetAPI.h index 055097cb7..6ef588bd6 100644 --- a/src/Config/Config_WidgetAPI.h +++ b/src/Config/Config_WidgetAPI.h @@ -78,7 +78,7 @@ class Config_WidgetAPI CONFIG_EXPORT bool getBooleanAttribute(const char* theAttributeName, bool theDefault) const; /// These fields are accessible for ModuleBase_WidgetFactory only - CONFIG_EXPORT Config_WidgetAPI(std::string theRawXml); + CONFIG_EXPORT Config_WidgetAPI(std::string theRawXml, const std::string theAttributePrefix = ""); //! Pass to the next (sibling) node of widget's xml definition. If impossible, returns false CONFIG_EXPORT bool toNextWidget(); //! Pass into the child node of widget's xml definition. If impossible, returns false @@ -90,6 +90,7 @@ class Config_WidgetAPI xmlDocPtr myDoc; //!< Pointer to the root of widget's xml definition xmlNodePtr myCurrentNode; //!< Pointer to the current node in the widget's xml definition std::string myFeatureId; + std::string myAttributePrefix; //!< prefix that must be added to the attribute name friend class ModuleBase_WidgetFactory; }; diff --git a/src/FiltersAPI/FiltersAPI_Feature.cpp b/src/FiltersAPI/FiltersAPI_Feature.cpp index 14bdbf665..5fe14fd73 100644 --- a/src/FiltersAPI/FiltersAPI_Feature.cpp +++ b/src/FiltersAPI/FiltersAPI_Feature.cpp @@ -23,6 +23,8 @@ #include #include +#include +#include FiltersAPI_Feature::FiltersAPI_Feature( const std::shared_ptr & theFeature) @@ -57,8 +59,8 @@ void FiltersAPI_Feature::setFilters(const std::list& theFilters) FiltersFeaturePtr aBase = std::dynamic_pointer_cast(feature()); for (std::list::const_iterator anIt = theFilters.begin(); anIt != theFilters.end(); ++anIt) { - aBase->addFilter((*anIt)->name()); - aBase->setReversed((*anIt)->name(), (*anIt)->isReversed()); + std::string aFilterID = aBase->addFilter((*anIt)->name()); + aBase->setReversed(aFilterID, (*anIt)->isReversed()); const std::list& anArgs = (*anIt)->arguments(); if (!anArgs.empty()) { @@ -68,7 +70,7 @@ void FiltersAPI_Feature::setFilters(const std::list& theFilters) std::list aBools; separateArguments(anArgs, aSelections, aTexts, aBools); - std::list aFilterArgs = aBase->filterArgs((*anIt)->name()); + std::list aFilterArgs = aBase->filterArgs(aFilterID); std::list::iterator aFIt = aFilterArgs.begin(); // first boolean argument is always "Reversed" flag AttributeBooleanPtr aReversedFlag = @@ -115,9 +117,12 @@ void FiltersAPI_Feature::dump(ModelHighAPI_Dumper& theDumper) const const std::string& aDocName = theDumper.name(aBase->document()); theDumper << "model.filters(" << aDocName << ", ["; + ModelAPI_FiltersFactory* aFFactory = ModelAPI_Session::get()->filters(); std::list aFilters = aBase->filters(); for (std::list::iterator aFIt = aFilters.begin(); aFIt != aFilters.end(); ++aFIt) { - FiltersAPI_Filter aFilter(*aFIt, aBase->filterArgs(*aFIt)); + // for multiple filters get original id + std::string aFilterKind = aFFactory->id(aFFactory->filter(*aFIt)); + FiltersAPI_Filter aFilter(aFilterKind, aBase->filterArgs(*aFIt)); if (aFIt != aFilters.begin()) theDumper << ", "; aFilter.dump(theDumper); diff --git a/src/FiltersPlugin/CMakeLists.txt b/src/FiltersPlugin/CMakeLists.txt index d80b52515..69f98f31f 100644 --- a/src/FiltersPlugin/CMakeLists.txt +++ b/src/FiltersPlugin/CMakeLists.txt @@ -193,4 +193,8 @@ ADD_UNIT_TESTS( Test2951.py Test17924.py Test17962.py + TestFilter_OnLine_Multi.py + TestFilter_OnPlane_Multi.py + TestFilter_OnPlaneSide_Multi.py + TestFilter_RelativeToSolid_Multi.py ) diff --git a/src/FiltersPlugin/FiltersPlugin_OnGeometry.h b/src/FiltersPlugin/FiltersPlugin_OnGeometry.h index 2d25d4266..c90e5dd87 100644 --- a/src/FiltersPlugin/FiltersPlugin_OnGeometry.h +++ b/src/FiltersPlugin/FiltersPlugin_OnGeometry.h @@ -48,9 +48,6 @@ public: virtual bool isOk(const GeomShapePtr& theShape, const ResultPtr&, const ModelAPI_FiltersArgs& theArgs) const override; - /// Returns True if the filter can be used several times within one filtering - virtual bool isMultiple() const { return true; } - /// Returns XML string which represents GUI of the filter virtual std::string xmlRepresentation() const override; diff --git a/src/FiltersPlugin/FiltersPlugin_OnLine.h b/src/FiltersPlugin/FiltersPlugin_OnLine.h index b609bd940..773af38eb 100644 --- a/src/FiltersPlugin/FiltersPlugin_OnLine.h +++ b/src/FiltersPlugin/FiltersPlugin_OnLine.h @@ -41,6 +41,9 @@ public: /// Returns true for any type because it supports all selection types virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override; + /// Returns True if the filter can be used several times within one selection + virtual bool isMultiple() const { return true; } + /// This method should contain the filter logic. It returns true if the given shape /// is accepted by the filter. /// \param theShape the given shape diff --git a/src/FiltersPlugin/FiltersPlugin_OnPlane.h b/src/FiltersPlugin/FiltersPlugin_OnPlane.h index 62fccd1fc..94c091489 100644 --- a/src/FiltersPlugin/FiltersPlugin_OnPlane.h +++ b/src/FiltersPlugin/FiltersPlugin_OnPlane.h @@ -41,6 +41,9 @@ public: /// Returns true for any type because it supports all selection types virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override; + /// Returns True if the filter can be used several times within one selection + virtual bool isMultiple() const { return true; } + /// This method should contain the filter logic. It returns true if the given shape /// is accepted by the filter. /// \param theShape the given shape diff --git a/src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h b/src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h index 9939e4588..eae3fee50 100644 --- a/src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h +++ b/src/FiltersPlugin/FiltersPlugin_OnPlaneSide.h @@ -41,6 +41,9 @@ public: /// Returns true for any type because it supports all selection types virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override; + /// Returns True if the filter can be used several times within one selection + virtual bool isMultiple() const { return true; } + /// This method should contain the filter logic. It returns true if the given shape /// is accepted by the filter. /// \param theShape the given shape diff --git a/src/FiltersPlugin/FiltersPlugin_RelativeToSolid.h b/src/FiltersPlugin/FiltersPlugin_RelativeToSolid.h index 821b9a7ec..70b616cc0 100644 --- a/src/FiltersPlugin/FiltersPlugin_RelativeToSolid.h +++ b/src/FiltersPlugin/FiltersPlugin_RelativeToSolid.h @@ -41,6 +41,9 @@ public: /// Returns true for any type because it supports all selection types virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override; + /// Returns True if the filter can be used several times within one selection + virtual bool isMultiple() const { return true; } + /// This method should contain the filter logic. It returns true if the given shape /// is accepted by the filter. /// \param theShape the given shape diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.cpp b/src/FiltersPlugin/FiltersPlugin_Selection.cpp index 7fe056aba..23343cf61 100644 --- a/src/FiltersPlugin/FiltersPlugin_Selection.cpp +++ b/src/FiltersPlugin/FiltersPlugin_Selection.cpp @@ -23,25 +23,48 @@ #include #include #include +#include // identifier of the reverse flag of a filter static const std::string kReverseAttrID(""); -void FiltersPlugin_Selection::addFilter(const std::string theFilterID) +std::string FiltersPlugin_Selection::addFilter(const std::string theFilterID) { ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters(); FilterPtr aFilter = aFactory->filter(theFilterID); + + std::string aFilterID = theFilterID; + if (aFilter->isMultiple()) { // check that there is already such filter, so, increment ID + std::list aFilters; + data()->allGroups(aFilters); + for(int anID = 0; true; anID++) { + if (anID != 0) { + std::ostringstream aStream; + aStream<<"_"<::iterator aFiltersIDs = aFilters.begin(); + for(; aFiltersIDs != aFilters.end(); aFiltersIDs++) { + if (*aFiltersIDs == aFilterID) + break; + } + if (aFiltersIDs == aFilters.end()) + break; + } + } + if (aFilter.get()) { std::shared_ptr aBool = std::dynamic_pointer_cast(data()->addFloatingAttribute( - kReverseAttrID, ModelAPI_AttributeBoolean::typeId(), theFilterID)); + kReverseAttrID, ModelAPI_AttributeBoolean::typeId(), aFilterID)); aBool->setValue(false); // not reversed by default // to add attributes related to the filter ModelAPI_FiltersArgs anArgs; anArgs.setFeature(std::dynamic_pointer_cast(data()->owner())); - anArgs.setFilter(theFilterID); + anArgs.setFilter(aFilterID); aFilter->initAttributes(anArgs); } + return aFilterID; } void FiltersPlugin_Selection::removeFilter(const std::string theFilterID) diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.h b/src/FiltersPlugin/FiltersPlugin_Selection.h index 8fe3850a7..1c494582d 100644 --- a/src/FiltersPlugin/FiltersPlugin_Selection.h +++ b/src/FiltersPlugin/FiltersPlugin_Selection.h @@ -59,7 +59,8 @@ public: // methods related to the filters management /// Adds a filter to the feature. Also initializes arguments of this filter. - FILTERS_EXPORT virtual void addFilter(const std::string theFilterID) override; + /// Returns the real identifier of the filter. + FILTERS_EXPORT virtual std::string addFilter(const std::string theFilterID) override; /// Removes an existing filter from the feature. FILTERS_EXPORT virtual void removeFilter(const std::string theFilterID) override; diff --git a/src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py new file mode 100644 index 000000000..9e23a8515 --- /dev/null +++ b/src/FiltersPlugin/Test/TestFilter_OnLine_Multi.py @@ -0,0 +1,46 @@ +# 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) +# two filters with two edges each +Filters = model.filters(Part_1_doc, [ + model.addFilter(name = "OnLine", args = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]")]), + model.addFilter(name = "OnLine", args = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Left]"), model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]")])]) +model.end() + +# 2 vertices on intersection of edges +Reference = { + model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Top]"): True, + model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Top]"): False, + model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Left][Box_1_1/Bottom]"): False, + model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"): False, + model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Top]"): False, + model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"): False, + model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]"): True, + model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Right][Box_1_1/Bottom]"): False +} + +model.checkFilter(Part_1_doc, model, Filters, Reference) diff --git a/src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py new file mode 100644 index 000000000..49f94d8c4 --- /dev/null +++ b/src/FiltersPlugin/Test/TestFilter_OnPlaneSide_Multi.py @@ -0,0 +1,88 @@ +# 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() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(20, 23, -19, 23) +SketchLine_2 = Sketch_1.addLine(-19, 23, -19, -21) +SketchLine_3 = Sketch_1.addLine(-19, -21, 20, -21) +SketchLine_4 = Sketch_1.addLine(20, -21, 20, 23) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 30, 0) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 20, [model.selection("SOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face")) +SketchLine_5 = Sketch_2.addLine(34, 36, -11, 36) +SketchLine_6 = Sketch_2.addLine(-11, 36, -11, -10) +SketchLine_7 = Sketch_2.addLine(-11, -10, 34, -10) +SketchLine_8 = Sketch_2.addLine(34, -10, 34, 36) +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result()) +SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result()) +SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result()) +SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result()) +ExtrusionCut_1.setNestedSketch(Sketch_2) +# two filters with different faces each, the second is reversed +Filters = model.filters(Part_1_doc, [ + model.addFilter(name = "OnPlaneSide", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7")]), + model.addFilter(name = "OnPlaneSide", exclude = True, args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6")]), + model.addFilter(name = "OnPlaneSide", args = [model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face")])]) +model.end() + +# 5 edges are in result +Reference = { + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): True, + model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): True, + model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/From_Face]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4])([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face])"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, +} + +model.checkFilter(Part_1_doc, model, Filters, Reference) diff --git a/src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py b/src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py new file mode 100644 index 000000000..dbe25bc6e --- /dev/null +++ b/src/FiltersPlugin/Test/TestFilter_OnPlane_Multi.py @@ -0,0 +1,143 @@ +# 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() +Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 20, 0) +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(40, 30, 5, 30) +SketchLine_2 = Sketch_1.addLine(5, 30, 5, 3) +SketchLine_3 = Sketch_1.addLine(5, 3, 40, 3) +SketchLine_4 = Sketch_1.addLine(40, 3, 40, 30) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +Extrusion_1.setNestedSketch(Sketch_1) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face")) +SketchLine_5 = Sketch_2.addLine(18, 39, 29, 39) +SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result()) +SketchLine_6 = Sketch_2.addLine(29, 39, 29, 21) +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result()) +SketchLine_7 = Sketch_2.addLine(29, 21, 46, 21) +SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result()) +SketchLine_8 = Sketch_2.addLine(46, 21, 46, 11) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result()) +SketchLine_9 = Sketch_2.addLine(46, 11, 29, 11) +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint()) +SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_9.result()) +SketchLine_10 = Sketch_2.addLine(29, 11, 29, -3) +SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint()) +SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_10.result()) +SketchLine_11 = Sketch_2.addLine(29, -3, 18, -3) +SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint()) +SketchLine_12 = Sketch_2.addLine(18, -3, 18, 11) +SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint()) +SketchConstraintVertical_6 = Sketch_2.setVertical(SketchLine_12.result()) +SketchLine_13 = Sketch_2.addLine(18, 11, 3, 11) +SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_13.startPoint()) +SketchLine_14 = Sketch_2.addLine(3, 11, 3, 21) +SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint()) +SketchConstraintVertical_7 = Sketch_2.setVertical(SketchLine_14.result()) +SketchLine_15 = Sketch_2.addLine(3, 21, 18, 21) +SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint()) +SketchConstraintHorizontal_6 = Sketch_2.setHorizontal(SketchLine_15.result()) +SketchLine_16 = Sketch_2.addLine(18, 21, 18, 39) +SketchConstraintCoincidence_15 = Sketch_2.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint()) +SketchConstraintCoincidence_16 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_16.endPoint()) +SketchConstraintVertical_8 = Sketch_2.setVertical(SketchLine_16.result()) +SketchConstraintHorizontal_7 = Sketch_2.setHorizontal(SketchLine_13.result()) +SketchConstraintHorizontal_8 = Sketch_2.setHorizontal(SketchLine_11.result()) +SketchConstraintCoincidence_17 = Sketch_2.setCoincident(SketchLine_16.result(), SketchLine_12.endPoint()) +SketchConstraintCoincidence_18 = Sketch_2.setCoincident(SketchLine_6.result(), SketchLine_10.startPoint()) +SketchConstraintCoincidence_19 = Sketch_2.setCoincident(SketchLine_15.result(), SketchLine_7.startPoint()) +SketchConstraintCoincidence_20 = Sketch_2.setCoincident(SketchLine_13.result(), SketchLine_10.startPoint()) +model.do() +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_16r-SketchLine_15r-SketchLine_14r-SketchLine_13r-SketchLine_12r-SketchLine_11r-SketchLine_10r-SketchLine_9r-SketchLine_8r-SketchLine_7r-SketchLine_6r-SketchLine_5r")], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")]) +# two smae filters with two planes each +Filters = model.filters(Part_1_doc, [ + model.addFilter(name = "OnPlane", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16"), model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6")]), + model.addFilter(name = "OnPlane", args = [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15"), model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13")])]) + +model.end() + +# 4 edges are in result: intersection of pairs of planes +Reference = { + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): True, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15])"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13]"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16]"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_15)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_13)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12])"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][Extrusion_1_1/From_Face]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6])"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False, + model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7])([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9])"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)2(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_12)2]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9]"): False, + model.selection("EDGE", "[Extrusion_1_1/From_Face][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, + model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1][(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2]"): False, + model.selection("EDGE", "[(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_1)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_6)(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4)(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_7)(Extrusion_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_2)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_16)2(ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face)2(ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_3)2(ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9)2][ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchLine_4]"): False, +} + +model.checkFilter(Part_1_doc, model, Filters, Reference) diff --git a/src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py b/src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py new file mode 100644 index 000000000..1007428f1 --- /dev/null +++ b/src/FiltersPlugin/Test/TestFilter_RelativeToSolid_Multi.py @@ -0,0 +1,61 @@ +# 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() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_1.addCircle(18.85055999990443, 20.40038647424626, 12.41450630559296) +SketchCircle_2 = Sketch_1.addCircle(25.08744138385902, 26.81117176326632, 2.271058181559462) +SketchCircle_2.setName("SketchCircle_3") +SketchCircle_2.result().setName("SketchCircle_3") +SketchCircle_2.results()[1].setName("SketchCircle_3_2") +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_3 = Sketch_2.addCircle(30.95603034069762, 31.40670583726882, 10.95693005417035) +SketchCircle_3.setName("SketchCircle_4") +SketchCircle_3.result().setName("SketchCircle_4") +SketchCircle_3.results()[1].setName("SketchCircle_4_2") +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_1/Face-SketchCircle_1_2r-SketchCircle_3_2r_wire")], model.selection(), 50, 0) +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Face-SketchCircle_4_2r_wire")], model.selection(), 40, -10) +Extrusion_3 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_3_2f")], model.selection(), 20, -30) +# Two filters to search all face inside of two solids +Filters = model.filters(Part_1_doc, [ + model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_1_1"), "in"]), + model.addFilter(name = "RelativeToSolid", args = [model.selection("SOLID", "Extrusion_2_1"), "in"])]) +model.end() + +# 3 faces of internal cylinder is inside +Reference = { + model.selection("FACE", "Extrusion_3_1/Generated_Face&Sketch_1/SketchCircle_3_2"): True, + model.selection("FACE", "Extrusion_3_1/From_Face"): True, + model.selection("FACE", "Extrusion_3_1/To_Face"): True, + model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2"): False, + model.selection("FACE", "Extrusion_1_1/From_Face"): False, + model.selection("FACE", "Extrusion_1_1/To_Face"): False, + model.selection("FACE", "Extrusion_2_1/Generated_Face&Sketch_2/SketchCircle_4_2"): False, + model.selection("FACE", "Extrusion_2_1/From_Face"): False, + model.selection("FACE", "Extrusion_2_1/To_Face"): False +} + +model.checkFilter(Part_1_doc, model, Filters, Reference) diff --git a/src/FiltersPlugin/doc/FiltersPlugin.rst b/src/FiltersPlugin/doc/FiltersPlugin.rst index 8e6d0babd..1e9aade08 100644 --- a/src/FiltersPlugin/doc/FiltersPlugin.rst +++ b/src/FiltersPlugin/doc/FiltersPlugin.rst @@ -33,6 +33,8 @@ In this panel: .. centered:: Filters **Horizontal faces** and **On plane** added to the property panel. +If filter is implemented as "Multiple", several instances of this filter may be added in one selection. Otherwise the added filter is removed from the "Add new filter..." list. + Each filter item can be deleted with help of |delete.icon| button. A filter can be reverced with help of toggle button |plus.icon|/|minus.icon|. Also a filter could have input fields in case if the filter has arguments. @@ -73,7 +75,7 @@ By default, the result of Selection feature all selectable entities from all Sha - **Result type:** Any - **Argument:** Any Shape, multiple OR selection accepted -- **Algorithm:** Returns the shapes which have the similar underlying geometry of the given Shape. Like all faces laying of the same geometrical surface or edges laying of the same geometrical surface or edges laying on the line. +- **Algorithm:** Returns the shapes which have the similar underlying geometry of the given Shape. Like all faces laying of the same geometrical surface or edges laying on the line. **On plane side** diff --git a/src/Model/Model_FiltersFactory.cpp b/src/Model/Model_FiltersFactory.cpp index f84febdfc..d02682d68 100644 --- a/src/Model/Model_FiltersFactory.cpp +++ b/src/Model/Model_FiltersFactory.cpp @@ -40,6 +40,21 @@ struct FilterArgs { std::string myFilterID; }; +/// Returns the filter ID without the filter index +static std::string pureFilterID(const std::string& theID) +{ + // remove from aPure "_" + number + "_" starting part + if (theID.size() > 3 && theID[0] == '_') { + int aNumDigits = 0; + while(theID[aNumDigits + 1] < '9' && theID[aNumDigits + 1] > '0') + aNumDigits++; + if (aNumDigits && theID[aNumDigits + 1] == '_') { + return theID.substr(aNumDigits + 2); + } + } + return theID; +} + bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature, ResultPtr theResult, GeomShapePtr theShape) @@ -63,7 +78,8 @@ bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature, theFiltersFeature->data()->allGroups(aGroups); for(std::list::iterator aGIter = aGroups.begin(); aGIter != aGroups.end(); aGIter++) { - if (myFilters.find(*aGIter) == myFilters.end()) + std::string aPureID = pureFilterID(*aGIter); + if (myFilters.find(aPureID) == myFilters.end()) continue; std::list > anAttrs; theFiltersFeature->data()->attributesOfGroup(*aGIter, anAttrs); @@ -73,7 +89,7 @@ bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature, if (anArgID.empty()) { // reverse flag std::shared_ptr aReverse = std::dynamic_pointer_cast(*anAttrIter); - FilterArgs aFArgs = { myFilters[*aGIter] , aReverse->value() , *aGIter }; + FilterArgs aFArgs = { myFilters[aPureID] , aReverse->value() , *aGIter }; aFilters.push_back(aFArgs); } else { @@ -113,7 +129,8 @@ std::list Model_FiltersFactory::filters(GeomAPI_Shape::ShapeType theT FilterPtr Model_FiltersFactory::filter(std::string theID) { - std::map::iterator aFound = myFilters.find(theID); + std::string aPureID = pureFilterID(theID); + std::map::iterator aFound = myFilters.find(aPureID); return aFound == myFilters.end() ? FilterPtr() : aFound->second; } diff --git a/src/ModelAPI/ModelAPI_FiltersFeature.h b/src/ModelAPI/ModelAPI_FiltersFeature.h index b47909943..9c2064d45 100644 --- a/src/ModelAPI/ModelAPI_FiltersFeature.h +++ b/src/ModelAPI/ModelAPI_FiltersFeature.h @@ -33,7 +33,8 @@ class ModelAPI_FiltersFeature: public ModelAPI_Feature { public: /// Adds a filter to the feature. Also initializes arguments of this filter. - virtual void addFilter(const std::string theFilterID) = 0; + /// Returns the real identifier of the filter. + virtual std::string addFilter(const std::string theFilterID) = 0; /// Removes an existing filter from the feature. virtual void removeFilter(const std::string theFilterID) = 0; diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index ab7b17e10..269d445b5 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -77,10 +77,11 @@ #include ModuleBase_WidgetFactory::ModuleBase_WidgetFactory(const std::string& theXmlRepresentation, - ModuleBase_IWorkshop* theWorkshop) + ModuleBase_IWorkshop* theWorkshop, + const std::string theAttributePrefix) : myWorkshop(theWorkshop) { - myWidgetApi = new Config_WidgetAPI(theXmlRepresentation); + myWidgetApi = new Config_WidgetAPI(theXmlRepresentation, theAttributePrefix); } ModuleBase_WidgetFactory::~ModuleBase_WidgetFactory() diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.h b/src/ModuleBase/ModuleBase_WidgetFactory.h index 90ea7428b..49fc9a053 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetFactory.h @@ -43,8 +43,10 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFactory /// Constructor /// \param theXmlRepresentation content of XML file /// \param theWorkshop reference to workshop instance - ModuleBase_WidgetFactory(const std::string& theXmlRepresentation, - ModuleBase_IWorkshop* theWorkshop); + /// \param theAttributePrefix prefix that must be added to the attribute name + ModuleBase_WidgetFactory(const std::string& theXmlRepresentation, + ModuleBase_IWorkshop* theWorkshop, + const std::string theAttributePrefix = ""); virtual ~ModuleBase_WidgetFactory(); /// Creates content widget for property panel diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp index f812ac262..6e916b7ab 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp @@ -143,12 +143,17 @@ ModuleBase_FilterItem::ModuleBase_FilterItem( : QWidget(theParent->filtersWidget()), myFilterID(theFilter), mySelection(std::dynamic_pointer_cast(theParent->feature())) { - std::string aXmlString = - ModelAPI_Session::get()->filters()->filter(theFilter)->xmlRepresentation(); + FilterPtr aFilter = ModelAPI_Session::get()->filters()->filter(theFilter); + std::string aXmlString = aFilter->xmlRepresentation(); if (aXmlString.length() == 0) addItemRow(this); else { - ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop()); + std::string anAttrPrefix; // this must be added to the attributes names for multiple filters + std::string aFilterKind = ModelAPI_Session::get()->filters()->id(aFilter); + if (theFilter != aFilterKind) { + anAttrPrefix = theFilter.substr(0, theFilter.size() - aFilterKind.size()); + } + ModuleBase_WidgetFactory aFactory(aXmlString, theParent->workshop(), anAttrPrefix); Config_ValidatorReader aValidatorReader(aXmlString, true); aValidatorReader.setFeatureId(mySelection->getKind()); aValidatorReader.readAll(); -- 2.30.2