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 @@ + + + + + + + + image/svg+xml + + + + + [Alexander Gryson] + + + fem-clip + 2017-03-11 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/ + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + image/svg+xml + + + + + [Alexander Gryson] + + + fem-clip + 2017-03-11 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/ + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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