diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index f2e33ab926..e50d5a40d0 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -22,7 +22,9 @@ import FreeCAD import FreeCADGui + from .manager import CommandManager +from femtools.femutils import is_of_type # Python command definitions @@ -68,8 +70,11 @@ class _ClippingPlaneAdd(CommandManager): self.is_active = "with_document" def Activated(self): - from femtools import femutils - overalboundbox = femutils.getBoundBoxOfAllDocumentShapes(FreeCAD.ActiveDocument) + from pivy import coin + from femtools.femutils import getBoundBoxOfAllDocumentShapes + from femtools.femutils import getSelectedFace + + overalboundbox = getBoundBoxOfAllDocumentShapes(FreeCAD.ActiveDocument) # print(overalboundbox) min_bb_length = (min(set([ overalboundbox.XLength, @@ -78,7 +83,7 @@ class _ClippingPlaneAdd(CommandManager): ]))) dbox = min_bb_length * 0.2 - aFace = femutils.getSelectedFace(FreeCADGui.Selection.getSelectionEx()) + aFace = getSelectedFace(FreeCADGui.Selection.getSelectionEx()) if aFace: f_CoM = aFace.CenterOfMass f_uvCoM = aFace.Surface.parameter(f_CoM) # u,v at CoM for normalAt calculation @@ -87,7 +92,6 @@ class _ClippingPlaneAdd(CommandManager): 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, @@ -333,10 +337,7 @@ class _MaterialMechanicalNonlinear(CommandManager): # test if there is a nonlinear material which has the selected material as base material for o in self.selobj.Document.Objects: if ( - hasattr(o, "Proxy") - and o.Proxy is not None - and hasattr(o.Proxy, "Type") - and o.Proxy.Type == "Fem::MaterialMechanicalNonlinear" + is_of_type(o, "Fem::MaterialMechanicalNonlinear") and o.LinearBaseMaterial == self.selobj ): FreeCAD.Console.PrintError( @@ -373,12 +374,10 @@ class _MaterialMechanicalNonlinear(CommandManager): break # set solver attribute for nonlinearity for ccxtools # CalculiX solver or new frame work CalculiX solver - if solver_object \ - and hasattr(solver_object, "Proxy") \ - and ( - solver_object.Proxy.Type == "Fem::FemSolverCalculixCcxTools" - or solver_object.Proxy.Type == "Fem::FemSolverObjectCalculix" - ): + if solver_object and ( + is_of_type(solver_object, "Fem::FemSolverCalculixCcxTools") + or is_of_type(solver_object, "Fem::FemSolverObjectCalculix") + ): FreeCAD.Console.PrintMessage( "Set MaterialNonlinearity and GeometricalNonlinearity to nonlinear for {}\n" .format(solver_object.Label) @@ -654,7 +653,7 @@ class _SolverCxxtools(CommandManager): def Activated(self): has_nonlinear_material_obj = False for m in self.active_analysis.Group: - if hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear": + if is_of_type(m, "Fem::MaterialMechanicalNonlinear"): has_nonlinear_material_obj = True FreeCAD.ActiveDocument.openTransaction("Create SolverCalculix") FreeCADGui.addModule("ObjectsFem") diff --git a/src/Mod/Fem/femcommands/manager.py b/src/Mod/Fem/femcommands/manager.py index c654944d08..f0d05cbc9e 100644 --- a/src/Mod/Fem/femcommands/manager.py +++ b/src/Mod/Fem/femcommands/manager.py @@ -28,12 +28,13 @@ __url__ = "http://www.freecadweb.org" # @{ import FreeCAD -from femtools import femutils + +from femtools.femutils import is_of_type if FreeCAD.GuiUp: + from PySide import QtCore import FreeCADGui import FemGui - from PySide import QtCore class CommandManager(object): @@ -162,7 +163,7 @@ class CommandManager(object): result_mesh = False analysis_members = FemGui.getActiveAnalysis().Group for o in analysis_members: - if femutils.is_of_type(o, "Fem::FemMeshResult"): + if is_of_type(o, "Fem::FemMeshResult"): result_mesh = True return result_mesh @@ -193,11 +194,7 @@ class CommandManager(object): def gmsh_femmesh_selected(self): sel = FreeCADGui.Selection.getSelection() - if ( - len(sel) == 1 - and hasattr(sel[0], "Proxy") - and sel[0].Proxy.Type == "Fem::FemMeshGmsh" - ): + if len(sel) == 1 and is_of_type(sel[0], "Fem::FemMeshGmsh"): self.selobj = sel[0] return True else: @@ -266,11 +263,7 @@ class CommandManager(object): def solver_elmer_selected(self): sel = FreeCADGui.Selection.getSelection() - if ( - len(sel) == 1 - and hasattr(sel[0], "Proxy") - and sel[0].Proxy.Type == "Fem::FemSolverObjectElmer" - ): + if len(sel) == 1 and is_of_type(sel[0], "Fem::FemSolverObjectElmer"): self.selobj = sel[0] return True else: diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemMeshGmsh.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemMeshGmsh.py index 0716c702a2..c7f16c86c1 100644 --- a/src/Mod/Fem/femguiobjects/_ViewProviderFemMeshGmsh.py +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemMeshGmsh.py @@ -43,6 +43,7 @@ import FreeCADGui import FemGui # from . import ViewProviderFemConstraint from femobjects import _FemMeshGmsh +from femtools.femutils import is_of_type # class _ViewProviderFemMeshGmsh(ViewProviderFemConstraint.ViewProxy): @@ -212,16 +213,12 @@ class _ViewProviderFemMeshGmsh: def canDropObjects(self): return True - # TODO use femutils module methods for type checking def canDragObject(self, dragged_object): - if hasattr(dragged_object, "Proxy") \ - and dragged_object.Proxy.Type == "Fem::MeshBoundaryLayer": - return True - elif hasattr(dragged_object, "Proxy") \ - and dragged_object.Proxy.Type == "Fem::MeshGroup": - return True - elif hasattr(dragged_object, "Proxy") \ - and dragged_object.Proxy.Type == "Fem::MeshRegion": + if ( + is_of_type(dragged_object, "Fem::MeshBoundaryLayer") + or is_of_type(dragged_object, "Fem::MeshGroup") + or is_of_type(dragged_object, "Fem::MeshRegion") + ): return True else: return False @@ -230,33 +227,29 @@ class _ViewProviderFemMeshGmsh: return True def dragObject(self, selfvp, dragged_object): - if hasattr(dragged_object, "Proxy") \ - and dragged_object.Proxy.Type == "Fem::MeshBoundaryLayer": + if is_of_type(dragged_object, "Fem::MeshBoundaryLayer"): objs = self.Object.MeshBoundaryLayerList objs.remove(dragged_object) self.Object.MeshBoundaryLayerList = objs - elif hasattr(dragged_object, "Proxy") and dragged_object.Proxy.Type == "Fem::MeshGroup": + elif is_of_type(dragged_object, "Fem::MeshGroup"): objs = self.Object.MeshGroupList objs.remove(dragged_object) self.Object.MeshGroupList = objs - elif hasattr(dragged_object, "Proxy") and dragged_object.Proxy.Type == "Fem::MeshRegion": + elif is_of_type(dragged_object, "Fem::MeshRegion"): objs = self.Object.MeshRegionList objs.remove(dragged_object) self.Object.MeshRegionList = objs def dropObject(self, selfvp, incoming_object): - if hasattr(incoming_object, "Proxy") \ - and incoming_object.Proxy.Type == "Fem::MeshBoundaryLayer": + if is_of_type(incoming_object, "Fem::MeshBoundaryLayer"): objs = self.Object.MeshBoundaryLayerList objs.append(incoming_object) self.Object.MeshBoundaryLayerList = objs - elif hasattr(incoming_object, "Proxy") \ - and incoming_object.Proxy.Type == "Fem::MeshGroup": + elif is_of_type(incoming_object, "Fem::MeshGroup"): objs = self.Object.MeshGroupList objs.append(incoming_object) self.Object.MeshGroupList = objs - elif hasattr(incoming_object, "Proxy") \ - and incoming_object.Proxy.Type == "Fem::MeshRegion": + elif is_of_type(incoming_object, "Fem::MeshRegion"): objs = self.Object.MeshRegionList objs.append(incoming_object) self.Object.MeshRegionList = objs @@ -383,28 +376,30 @@ class _TaskPanel: def run_gmsh(self): QApplication.setOverrideCursor(Qt.WaitCursor) part = self.mesh_obj.Part - if self.mesh_obj.MeshRegionList: - # other part obj might not have a Proxy, thus an exception would be raised - if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): - if part.Proxy.Type == "FeatureBooleanFragments" \ - or part.Proxy.Type == "FeatureSlice" \ - or part.Proxy.Type == "FeatureXOR": - error_message = ( - "The shape to mesh is a boolean split tools Compound " - "and the mesh has mesh region list. " - "Gmsh could return unexpected meshes in such circumstances. " - "It is strongly recommended to extract the shape " - "to mesh from the Compound and use this one." - ) - qtbox_title = ( - "Shape to mesh is a BooleanFragmentsCompound " - "and mesh regions are defined" - ) - QtGui.QMessageBox.critical( - None, - qtbox_title, - error_message - ) + if ( + self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound" + and ( + is_of_type(part, "FeatureBooleanFragments") + or is_of_type(part, "FeatureSlice") + or is_of_type(part, "FeatureXOR") + ) + ): + error_message = ( + "The shape to mesh is a boolean split tools Compound " + "and the mesh has mesh region list. " + "Gmsh could return unexpected meshes in such circumstances. " + "It is strongly recommended to extract the shape " + "to mesh from the Compound and use this one." + ) + qtbox_title = ( + "Shape to mesh is a BooleanFragmentsCompound " + "and mesh regions are defined" + ) + QtGui.QMessageBox.critical( + None, + qtbox_title, + error_message + ) self.Start = time.time() self.form.l_time.setText("Time: {0:4.1f}: ".format(time.time() - self.Start)) self.console_message_gmsh = "" diff --git a/src/Mod/Fem/femmesh/gmshtools.py b/src/Mod/Fem/femmesh/gmshtools.py index 8d6b2d3581..bf577033f7 100644 --- a/src/Mod/Fem/femmesh/gmshtools.py +++ b/src/Mod/Fem/femmesh/gmshtools.py @@ -366,23 +366,25 @@ class GmshTools(): # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 # http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520 part = self.part_obj - if self.mesh_obj.MeshRegionList: - # other part obj might not have a Proxy, thus an exception would be raised - if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): - if part.Proxy.Type == "FeatureBooleanFragments" \ - or part.Proxy.Type == "FeatureSlice" \ - or part.Proxy.Type == "FeatureXOR": - error_message = ( - " The mesh to shape is a boolean split tools Compound " - "and the mesh has mesh region list. " - "Gmsh could return unexpected meshes in such circumstances. " - "It is strongly recommended to extract the shape to mesh " - "from the Compound and use this one." - ) - Console.PrintError(error_message + "\n") - # TODO: no gui popup because FreeCAD will be in a endless output loop - # as long as the pop up is on --> maybe find a better solution for - # either of both --> thus the pop up is in task panel + if ( + self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound" + and ( + femutils.is_of_type(part, "FeatureBooleanFragments") + or femutils.is_of_type(part, "FeatureSlice") + or femutils.is_of_type(part, "FeatureXOR") + ) + ): + error_message = ( + " The mesh to shape is a boolean split tools Compound " + "and the mesh has mesh region list. " + "Gmsh could return unexpected meshes in such circumstances. " + "It is strongly recommended to extract the shape to mesh " + "from the Compound and use this one." + ) + Console.PrintError(error_message + "\n") + # TODO: no gui popup because FreeCAD will be in a endless output loop + # as long as the pop up is on --> maybe find a better solution for + # either of both --> thus the pop up is in task panel for mr_obj in self.mesh_obj.MeshRegionList: # print(mr_obj.Name) # print(mr_obj.CharacteristicLength) diff --git a/src/Mod/Fem/femresult/resulttools.py b/src/Mod/Fem/femresult/resulttools.py index e3e0b276e6..a6a2fcdfac 100644 --- a/src/Mod/Fem/femresult/resulttools.py +++ b/src/Mod/Fem/femresult/resulttools.py @@ -26,11 +26,13 @@ __url__ = "http://www.freecadweb.org" ## \addtogroup FEM # @{ -import FreeCAD -from femtools import femutils import numpy as np from math import isnan +import FreeCAD + +from femtools.femutils import is_of_type + def purge_results(analysis): """Removes all result objects and result meshes from an analysis group @@ -42,10 +44,8 @@ def purge_results(analysis): """ for m in analysis.Group: - if (m.isDerivedFrom("Fem::FemResultObject")): - if m.Mesh \ - and hasattr(m.Mesh, "Proxy") \ - and m.Mesh.Proxy.Type == "Fem::FemMeshResult": + if m.isDerivedFrom("Fem::FemResultObject"): + if m.Mesh and is_of_type(m.Mesh, "Fem::FemMeshResult"): analysis.Document.removeObject(m.Mesh.Name) analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute() @@ -54,7 +54,7 @@ def purge_results(analysis): # we could run into trouble in one loop because # we will delete objects and try to access them later for m in analysis.Group: - if femutils.is_of_type(m, "Fem::FemMeshResult"): + if is_of_type(m, "Fem::FemMeshResult"): analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute() @@ -418,7 +418,7 @@ def get_concrete_nodes(res_obj): for obj in res_obj.getParentGroup().Group: if obj.isDerivedFrom("App::MaterialObjectPython") \ - and femutils.is_of_type(obj, "Fem::MaterialReinforced"): + and is_of_type(obj, "Fem::MaterialReinforced"): FreeCAD.Console.PrintMessage("ReinforcedMaterial\n") if obj.References == []: for iic in range(nsr): @@ -430,7 +430,7 @@ def get_concrete_nodes(res_obj): for cn in concrete_nodes: ic[cn - 1] = 1 elif obj.isDerivedFrom("App::MaterialObjectPython") \ - and femutils.is_of_type(obj, "Fem::Material"): + and is_of_type(obj, "Fem::Material"): FreeCAD.Console.PrintMessage("No ReinforcedMaterial\n") if obj.References == []: for iic in range(nsr): @@ -472,7 +472,7 @@ def add_principal_stress_reinforced(res_obj): # material parameter for obj in res_obj.getParentGroup().Group: - if femutils.is_of_type(obj, "Fem::MaterialReinforced"): + if is_of_type(obj, "Fem::MaterialReinforced"): matrix_af = float( FreeCAD.Units.Quantity(obj.Material["AngleOfFriction"]).getValueAs("rad") )