diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc
index 6182fcf14b..68f34efa1a 100755
--- a/src/Mod/Fem/Gui/Resources/Fem.qrc
+++ b/src/Mod/Fem/Gui/Resources/Fem.qrc
@@ -15,6 +15,8 @@
icons/fem-cfd-analysis.svg
icons/fem-clip.svg
icons/fem-clip-scalar.svg
+ icons/fem-clipping-plane-add.svg
+ icons/fem-clipping-plane-remove-all.svg
icons/fem-constraint-bearing.svg
icons/fem-constraint-contact.svg
icons/fem-constraint-displacement.svg
diff --git a/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-add.svg b/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-add.svg
new file mode 100644
index 0000000000..d693643202
--- /dev/null
+++ b/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-add.svg
@@ -0,0 +1,169 @@
+
+
+
+
diff --git a/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-remove-all.svg b/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-remove-all.svg
new file mode 100644
index 0000000000..2a4e607f71
--- /dev/null
+++ b/src/Mod/Fem/Gui/Resources/icons/fem-clipping-plane-remove-all.svg
@@ -0,0 +1,199 @@
+
+
+
+
diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp
index a54e354438..3ea2dfe6a5 100755
--- a/src/Mod/Fem/Gui/Workbench.cpp
+++ b/src/Mod/Fem/Gui/Workbench.cpp
@@ -137,7 +137,6 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
results->setCommand("Results");
*results << "FEM_ResultsPurge"
<< "FEM_ResultShow";
-
#ifdef FC_USE_VTK
*results << "Separator"
<< "FEM_PostApplyChanges"
@@ -154,6 +153,11 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
<< "FEM_PostCreateFunctions";
#endif
+ Gui::ToolBarItem* utils = new Gui::ToolBarItem(root);
+ utils->setCommand("Results");
+ *utils << "FEM_ClippingPlaneAdd"
+ << "FEM_ClippingPlaneRemoveAll";
+
return root;
}
@@ -258,7 +262,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const
results->setCommand("&Results");
*results << "FEM_ResultsPurge"
<< "FEM_ResultShow";
-
#ifdef FC_USE_VTK
*results << "Separator"
<< "FEM_PostApplyChanges"
@@ -275,5 +278,11 @@ Gui::MenuItem* Workbench::setupMenuBar() const
<< "FEM_PostCreateFunctions";
#endif
+ Gui::MenuItem* utils = new Gui::MenuItem;
+ root->insertItem(item, utils);
+ utils->setCommand("Utilities");
+ *utils << "FEM_ClippingPlaneAdd"
+ << "FEM_ClippingPlaneRemoveAll";
+
return root;
}
diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py
index 2d5e66c3e4..0dd7276feb 100644
--- a/src/Mod/Fem/femcommands/commands.py
+++ b/src/Mod/Fem/femcommands/commands.py
@@ -52,6 +52,60 @@ class _CommandFemAnalysis(CommandManager):
FreeCAD.ActiveDocument.recompute()
+class _CommandFemClippingPlaneAdd(CommandManager):
+ "The FEM_ClippingPlaneAdd command definition"
+ def __init__(self):
+ super(_CommandFemClippingPlaneAdd, self).__init__()
+ self.resources = {'Pixmap': 'fem-clipping-plane-add',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Clipping Plane", "Clipping plane on face"),
+ # 'Accel': "Z, Z",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Clipping Plane", "Add a clipping plane on a selected face")}
+ self.is_active = 'with_document'
+
+ def Activated(self):
+ from femtools import femutils
+ overalboundbox = femutils.getBoundBoxOfAllDocumentShapes(FreeCAD.ActiveDocument)
+ # print(overalboundbox)
+ min_bb_length = (min(set([overalboundbox.XLength, overalboundbox.YLength, overalboundbox.ZLength])))
+ dbox = min_bb_length * 0.2
+
+ aFace = femutils.getSelectedFace(FreeCADGui.Selection.getSelectionEx())
+ if aFace:
+ f_CoM = aFace.CenterOfMass
+ f_uvCoM = aFace.Surface.parameter(f_CoM) # u,v at CoM for normalAt calculation
+ f_normal = aFace.normalAt(f_uvCoM[0], f_uvCoM[1])
+ else:
+ f_CoM = FreeCAD.Vector(0, 0, 0)
+ f_normal = FreeCAD.Vector(0, 0, 1)
+
+ from pivy import coin
+ coin_normal_vector = coin.SbVec3f(-f_normal.x, -f_normal.y, -f_normal.z)
+ coin_bound_box = coin.SbBox3f(f_CoM.x - dbox, f_CoM.y - dbox, f_CoM.z - dbox * 0.15, f_CoM.x + dbox, f_CoM.y + dbox, f_CoM.z + dbox * 0.15)
+ clip_plane = coin.SoClipPlaneManip()
+ clip_plane.setValue(coin_bound_box, coin_normal_vector, 1)
+ FreeCADGui.ActiveDocument.ActiveView.getSceneGraph().insertChild(clip_plane, 1)
+
+
+class _CommandFemClippingPlaneRemoveAll(CommandManager):
+ "The FEM_ClippingPlaneemoveAll command definition"
+ def __init__(self):
+ super(_CommandFemClippingPlaneRemoveAll, self).__init__()
+ self.resources = {'Pixmap': 'fem-clipping-plane-remove-all',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Clipping Plane", "remove all clipping planes"),
+ # 'Accel': "Z, Z",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Clipping Plane", "remove all clipping planes")}
+ self.is_active = 'with_document'
+
+ def Activated(self):
+ line1 = 'for node in list(sg.getChildren()):\n'
+ line2 = ' if isinstance(node, coin.SoClipPlane):\n'
+ line3 = ' sg.removeChild(node)'
+ FreeCADGui.doCommand("from pivy import coin")
+ FreeCADGui.doCommand("sg = Gui.ActiveDocument.ActiveView.getSceneGraph()")
+ FreeCADGui.doCommand("nodes = sg.getChildren()")
+ FreeCADGui.doCommand(line1 + line2 + line3)
+
+
class _CommandFemConstraintBodyHeatSource(CommandManager):
"The FEM_ConstraintBodyHeatSource command definition"
def __init__(self):
@@ -773,6 +827,8 @@ class _CommandFemSolverZ88(CommandManager):
# the string in add command will be the page name on FreeCAD wiki
FreeCADGui.addCommand('FEM_Analysis', _CommandFemAnalysis())
+FreeCADGui.addCommand('FEM_ClippingPlaneAdd', _CommandFemClippingPlaneAdd())
+FreeCADGui.addCommand('FEM_ClippingPlaneRemoveAll', _CommandFemClippingPlaneRemoveAll())
FreeCADGui.addCommand('FEM_ConstraintBodyHeatSource', _CommandFemConstraintBodyHeatSource())
FreeCADGui.addCommand('FEM_ConstraintElectrostaticPotential', _CommandFemConstraintElectrostaticPotential())
FreeCADGui.addCommand('FEM_ConstraintFlowVelocity', _CommandFemConstraintFlowVelocity())
diff --git a/src/Mod/Fem/femtools/femutils.py b/src/Mod/Fem/femtools/femutils.py
index 6dccf67d47..f29d90c5ab 100644
--- a/src/Mod/Fem/femtools/femutils.py
+++ b/src/Mod/Fem/femtools/femutils.py
@@ -27,6 +27,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
+import FreeCAD
import FreeCAD as App
@@ -100,3 +101,37 @@ def isDerivedFrom(obj, t):
obj.Proxy.Type == t):
return True
return obj.isDerivedFrom(t)
+
+
+def getBoundBoxOfAllDocumentShapes(doc):
+ overalboundbox = None
+ for o in doc.Objects:
+ if hasattr(o, 'Shape'):
+ try:
+ bb = o.Shape.BoundBox
+ except:
+ bb = None
+ if bb.isValid():
+ if not overalboundbox:
+ overalboundbox = bb
+ overalboundbox.add(bb)
+ return overalboundbox
+
+
+def getSelectedFace(selectionex):
+ aFace = None
+ # print(selectionex)
+ if len(selectionex) != 1:
+ FreeCAD.Console.PrintMessage('no or more than one object selected')
+ else:
+ sel = selectionex[0]
+ if len(sel.SubObjects) != 1:
+ FreeCAD.Console.PrintMessage('more than one element selected')
+ else:
+ aFace = sel.SubObjects[0]
+ if aFace.ShapeType != 'Face':
+ FreeCAD.Console.PrintMessage('not a Face selected')
+ else:
+ FreeCAD.Console.PrintMessage(':-)')
+ return aFace
+ return aFace