FEM: improve Python type checking and Python imports

This commit is contained in:
Bernd Hahnebach
2020-03-12 10:00:57 +01:00
parent 8ddbd110b6
commit 0e04844053
5 changed files with 85 additions and 96 deletions

View File

@@ -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")

View File

@@ -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:

View File

@@ -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 = ""

View File

@@ -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)

View File

@@ -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")
)