FiltersPlugin_OnLine.h
FiltersPlugin_OnGeometry.h
FiltersPlugin_OnPlaneSide.h
+ FiltersPlugin_OppositeToEdge.h
)
SET(PROJECT_SOURCES
FiltersPlugin_OnLine.cpp
FiltersPlugin_OnGeometry.cpp
FiltersPlugin_OnPlaneSide.cpp
+ FiltersPlugin_OppositeToEdge.cpp
)
SET(PROJECT_LIBRARIES
TestFilter_OnGeometry_Face.py
TestFilter_OnPlaneSide_Face.py
TestFilter_OnPlaneSide_Plane.py
+ TestFilter_OppositeToEdge.py
TestFilter_HorizontalFaces.py
TestFilter_VerticalFaces.py
)
--- /dev/null
+// 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_OppositeToEdge.h"
+
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Tools.h>
+
+#include <GeomAPI_Shape.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <map>
+
+typedef std::map<GeomShapePtr, SetOfShapes, GeomAPI_Shape::Comparator> MapShapeAndAncestors;
+
+static void mapEdgesAndFaces(const GeomShapePtr theShape, MapShapeAndAncestors& theMap)
+{
+ GeomAPI_ShapeExplorer aFExp(theShape, GeomAPI_Shape::FACE);
+ for (; aFExp.more(); aFExp.next()) {
+ GeomShapePtr aFace = aFExp.current();
+ GeomAPI_ShapeExplorer aEExp(aFace, GeomAPI_Shape::EDGE);
+ for (; aEExp.more(); aEExp.next())
+ theMap[aEExp.current()].insert(aFace);
+ }
+}
+
+// Return edge in the quadratic face opposite to the given one.
+// If the face is not quadratic, returns empty shape.
+static GeomShapePtr oppositeEdgeInQuadFace(const GeomShapePtr theEdge,
+ const GeomShapePtr theFace)
+{
+ static int THE_QUAD = 4;
+
+ int aNbEdges = 0;
+ int anOriginalEdgeIndex = -THE_QUAD;
+ GeomShapePtr anOppositeEdge;
+ GeomAPI_ShapeExplorer anExp(theFace, GeomAPI_Shape::EDGE);
+ while (anExp.more()) {
+ if (anExp.current()->isSame(theEdge))
+ anOriginalEdgeIndex = aNbEdges;
+ else if (aNbEdges == anOriginalEdgeIndex + THE_QUAD / 2) {
+ anOppositeEdge = anExp.current();
+ if (aNbEdges >= THE_QUAD)
+ break;
+ }
+
+ ++aNbEdges;
+ anExp.next();
+ if (!anExp.more()) {
+ if (aNbEdges != THE_QUAD) {
+ // not quad face
+ anOppositeEdge = GeomShapePtr();
+ break;
+ }
+ if (!anOppositeEdge)
+ anExp.reinit();
+ }
+ }
+ return anOppositeEdge;
+}
+
+// Find all opposite edges for the given.
+static void cacheOppositeEdge(const GeomShapePtr theEdge,
+ const MapShapeAndAncestors& theEdgeToFaces,
+ SetOfShapes& theCache)
+{
+ MapShapeAndAncestors::const_iterator aFound = theEdgeToFaces.find(theEdge);
+ if (aFound == theEdgeToFaces.end())
+ return;
+
+ for (SetOfShapes::const_iterator aFIt = aFound->second.begin();
+ aFIt != aFound->second.end(); ++aFIt) {
+ GeomShapePtr anOpposite = oppositeEdgeInQuadFace(theEdge, *aFIt);
+ if (anOpposite && theCache.find(anOpposite) == theCache.end()) {
+ theCache.insert(anOpposite);
+ cacheOppositeEdge(anOpposite, theEdgeToFaces, theCache);
+ }
+ }
+}
+
+static void cacheOppositeEdges(const GeomShapePtr theTopLevelShape,
+ const GeomShapePtr theEdge,
+ SetOfShapes& theCache)
+{
+ if (!theTopLevelShape || !theEdge)
+ return;
+
+ MapShapeAndAncestors anEdgesToFaces;
+ mapEdgesAndFaces(theTopLevelShape, anEdgesToFaces);
+
+ // keep the original edge
+ theCache.insert(theEdge);
+ // cache opposite edges
+ cacheOppositeEdge(theEdge, anEdgesToFaces, theCache);
+}
+
+
+bool FiltersPlugin_OppositeToEdge::isSupported(GeomAPI_Shape::ShapeType theType) const
+{
+ return theType == GeomAPI_Shape::EDGE;
+}
+
+bool FiltersPlugin_OppositeToEdge::isOk(const GeomShapePtr& theShape,
+ const ModelAPI_FiltersArgs& theArgs) const
+{
+ AttributePtr aAttr = theArgs.argument("OppositeToEdge");
+ AttributeSelectionPtr aList = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aAttr);
+ if (!aList.get())
+ return false;
+ GeomShapePtr anEdge = aList->value();
+ if (!myOriginalEdge || !myOriginalEdge->isSame(anEdge)) {
+ // new edge is selected, need to update the cache
+ const_cast<FiltersPlugin_OppositeToEdge*>(this)->myOriginalEdge = anEdge;
+ const_cast<FiltersPlugin_OppositeToEdge*>(this)->myCachedShapes.clear();
+ }
+
+ if (myCachedShapes.empty()) {
+ ResultBodyPtr aBaseResult = ModelAPI_Tools::bodyOwner(aList->context(), true);
+ if (!aBaseResult.get())
+ return false;
+
+ cacheOppositeEdges(aBaseResult->shape(), anEdge,
+ const_cast<FiltersPlugin_OppositeToEdge*>(this)->myCachedShapes);
+ }
+
+ return myCachedShapes.find(theShape) != myCachedShapes.end();
+}
+
+static std::string XMLRepresentation =
+"<filter id = \"OppositeToEdge\">"
+" <shape_selector id=\"OppositeToEdge__OppositeToEdge\""
+" label=\"Edge:\""
+" tooltip=\"Select edge.\""
+" shape_types=\"edges\">"
+" <validator id=\"GeomValidators_ShapeType\" parameters=\"line\"/>"
+" </shape_selector>"
+"</filter>";
+
+
+std::string FiltersPlugin_OppositeToEdge::xmlRepresentation() const
+{
+ return XMLRepresentation;
+}
+
+void FiltersPlugin_OppositeToEdge::initAttributes(ModelAPI_FiltersArgs& theArguments)
+{
+ theArguments.initAttribute("OppositeToEdge", ModelAPI_AttributeSelection::typeId());
+}
--- /dev/null
+// 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_OPPOSITETOEDGE_H_
+#define FILTERSPLUGIN_OPPOSITETOEDGE_H_
+
+#include "FiltersPlugin.h"
+
+#include <GeomAPI_Shape.h>
+#include <ModelAPI_Filter.h>
+
+#include <set>
+
+typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShapes;
+
+/**\class FiltersPlugin_OppositeToEdge
+* \ingroup DataModel
+* \brief Filter for edges of quadrangular faces opposite to the selected edge
+*/
+class FiltersPlugin_OppositeToEdge : public ModelAPI_Filter
+{
+public:
+ FiltersPlugin_OppositeToEdge() : ModelAPI_Filter() {}
+
+ virtual const std::string& name() const {
+ static const std::string kName("Opposite to an edge");
+ 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;
+
+private:
+ /// Original edge selected for filtering
+ GeomShapePtr myOriginalEdge;
+ /// Shapes applicable for the filter
+ SetOfShapes myCachedShapes;
+};
+
+#endif
\ No newline at end of file
#include "FiltersPlugin_OnLine.h"
#include "FiltersPlugin_OnGeometry.h"
#include "FiltersPlugin_OnPlaneSide.h"
+#include "FiltersPlugin_OppositeToEdge.h"
#include <ModelAPI_Session.h>
#include <ModelAPI_FiltersFactory.h>
aFactory->registerFilter("OnLine", new FiltersPlugin_OnLine);
aFactory->registerFilter("OnGeometry", new FiltersPlugin_OnGeometry);
aFactory->registerFilter("OnPlaneSide", new FiltersPlugin_OnPlaneSide);
+ aFactory->registerFilter("OppositeToEdge", new FiltersPlugin_OppositeToEdge);
ModelAPI_Session::get()->registerPlugin(this);
}
--- /dev/null
+# 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, 100, 100, 100)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], -50, -50, -50)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), model.selection("EDGE", "PartSet/OX"), 30)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 30)
+Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), model.selection("EDGE", "PartSet/OZ"), 30)
+Partition_1_objects = [model.selection("SOLID", "Translation_1_1"), model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2"), model.selection("FACE", "Plane_3")]
+Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, 20190506)
+Filters = model.filters(Part_1_doc, [model.addFilter(name = "OppositeToEdge", args = [model.selection("EDGE", "Partition_1_1_7/Generated_Edge&Plane_2/Plane_2&Plane_1/Plane_1")])])
+model.end()
+
+from GeomAPI import *
+
+Reference = {}
+# Faces are not applicable
+ResultBox_1 = Partition_1.result().resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.FACE)
+while exp.more():
+ Reference[model.selection(ResultBox_1, exp.current())] = False
+ exp.next()
+# Vertices are not applicable too
+exp = GeomAPI_ShapeExplorer(ResultBox_1.shape(), GeomAPI_Shape.VERTEX)
+while exp.more():
+ Reference[model.selection(ResultBox_1, exp.current())] = False
+ exp.next()
+
+# Edges of the partitioned box.
+# Note: the expected values have to be updated if ShapeExplorer will return another order of sub-shapes.
+
+# sub-result 0
+SubResult = Partition_1.result().subResult(0).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+
+# sub-result 1
+SubResult = Partition_1.result().subResult(1).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+
+# sub-result 2
+SubResult = Partition_1.result().subResult(2).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+ Reference[model.selection(SubResult, exp.current())] = False
+ exp.next()
+
+# sub-result 3
+SubResult = Partition_1.result().subResult(3).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+ Reference[model.selection(SubResult, exp.current())] = False
+ exp.next()
+
+# sub-result 4
+SubResult = Partition_1.result().subResult(4).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+
+# sub-result 5
+SubResult = Partition_1.result().subResult(5).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+ Reference[model.selection(SubResult, exp.current())] = False
+ exp.next()
+
+# sub-result 6
+SubResult = Partition_1.result().subResult(6).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+Reference[model.selection(SubResult, exp.current())] = False; exp.next()
+Reference[model.selection(SubResult, exp.current())] = True; exp.next()
+
+# sub-result 7
+SubResult = Partition_1.result().subResult(7).resultSubShapePair()[0]
+exp = GeomAPI_ShapeExplorer(SubResult.shape(), GeomAPI_Shape.EDGE)
+while exp.more():
+ Reference[model.selection(SubResult, exp.current())] = False
+ exp.next()
+
+model.checkFilter(Part_1_doc, model, Filters, Reference)