FEM: concrete, add task panel to select matrix and reinforcement material

This commit is contained in:
Bernd Hahnebach
2019-06-16 18:26:25 +02:00
parent a95f2d6153
commit 55fc22b4b8
3 changed files with 598 additions and 3 deletions

View File

@@ -401,6 +401,7 @@ SET(FemGuiPythonUI_SRCS
Resources/ui/FlowVelocity.ui
Resources/ui/InitialFlowVelocity.ui
Resources/ui/Material.ui
Resources/ui/MaterialReinforcement.ui
Resources/ui/MeshBoundaryLayer.ui
Resources/ui/MeshGmsh.ui
Resources/ui/MeshGroup.ui

View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FemMaterial</class>
<widget class="QWidget" name="FemMaterial">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>448</height>
</rect>
</property>
<property name="windowTitle">
<string>FEM material</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_desc">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1677215</height>
</size>
</property>
<property name="title">
<string>Matrix Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QComboBox" name="cb_materials_m">
<item>
<property name="text">
<string>Choose</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="l_name_m">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pb_edit_m">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Properties</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="l_description_m">
<property name="text">
<string>Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_desc_2">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1677215</height>
</size>
</property>
<property name="title">
<string>Reinforcement Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QComboBox" name="cb_materials_r">
<item>
<property name="text">
<string>Choose</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="l_name_r">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pb_edit_r">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Properties</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="l_description_r">
<property name="text">
<string>Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -33,6 +33,15 @@ import FemGui # needed to display the icons in TreeView
False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui'
# task panel
# from . import FemSelectionWidgets
from PySide import QtCore
from PySide import QtGui
import sys
if sys.version_info.major >= 3:
unicode = str
class _ViewProviderFemMaterialReinforced:
"A View Provider for the FemMaterialReinfocement object"
def __init__(self, vobj):
@@ -58,9 +67,19 @@ class _ViewProviderFemMaterialReinforced:
return
def setEdit(self, vobj, mode=0):
# avoid edit mode by return False
# https://forum.freecadweb.org/viewtopic.php?t=12139&start=10#p161062
return False
# hide all meshes
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Fem::FemMeshObject"):
o.ViewObject.hide()
# hide all meshes
for o in FreeCAD.ActiveDocument.Objects:
if o.isDerivedFrom("Fem::FemMeshObject"):
o.ViewObject.hide()
# show task panel
taskd = _TaskPanelFemMaterialReinforced(self.Object)
taskd.obj = vobj.Object
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self, vobj, mode=0):
FreeCADGui.Control.closeDialog()
@@ -87,3 +106,395 @@ class _ViewProviderFemMaterialReinforced:
def __setstate__(self, state):
return None
class _TaskPanelFemMaterialReinforced:
'''The editmode TaskPanel for FemMaterialReinforced objects'''
if sys.version_info.major >= 3:
unicode = str
def __init__(self, obj):
FreeCAD.Console.PrintMessage('\n') # empty line on start task panel
self.obj = obj
# init matrix and reinforcement material
self.material_m = self.obj.Material
self.card_path_m = ''
self.has_transient_mat_m = False
self.material_r = self.obj.Reinforcement
self.card_path_r = ''
self.has_transient_mat_r = False
# mat_card is the FCMat file
# card_name is the file name of the mat_card
# card_path is the whole file path of the mat_card
# material_name is the value of the key name in FreeCAD material dictionary
# they might not match because of special letters in the material_name which are
# changed in the card_name to english standard characters
# init for collecting all mat data and icons
self.materials = {} # { card_path : FreeCAD material dict }
self.cards = {} # { card_path : card_names, ... }
self.icons = {} # { card_path : icon_path }
# parameter widget
self.parameterWidget = FreeCADGui.PySideUic.loadUi(
FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/MaterialReinforcement.ui"
)
# globals
QtCore.QObject.connect(
self.parameterWidget.cb_materials_m,
QtCore.SIGNAL("activated(int)"),
self.choose_material_m
)
QtCore.QObject.connect(
self.parameterWidget.pb_edit_m,
QtCore.SIGNAL("clicked()"),
self.edit_material_m
)
QtCore.QObject.connect(
self.parameterWidget.cb_materials_r,
QtCore.SIGNAL("activated(int)"),
self.choose_material_r
)
QtCore.QObject.connect(
self.parameterWidget.pb_edit_r,
QtCore.SIGNAL("clicked()"),
self.edit_material_r
)
# get all available materials (fill self.materials, self.cards and self.icons)
from materialtools.cardutils import import_materials as getmats
self.materials, self.cards, self.icons = getmats()
# fill the material comboboxes with material cards
self.add_cards_to_combo_boxes()
# search for exact the mat_card_m and mat_card_r in all known cards
# choose the current matrix material
self.card_path_m = self.get_material_card(self.material_m)
FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_m))
if not self.card_path_m:
# we have not found our material in self.materials dict :-(
# we're going to add a user-defined temporary material: a document material
FreeCAD.Console.PrintMessage(
"Previously used material card cannot be found in material directories. "
"Add document material.\n"
)
self.card_path_m = '_Document_Matrix_Material'
self.materials[self.card_path_m] = self.material_m
self.parameterWidget.cb_materials_m.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_m,
self.card_path_m
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# print(index)
# fill input fields and set the current material in the cb widget
self.choose_material_m(index)
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Previously used material card was found in material directories. "
"We will use this material.\n"
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# set the current material in the cb widget
self.choose_material_m(index)
# choose the current reinforcement material
self.card_path_r = self.get_material_card(self.material_r)
FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_r))
if not self.card_path_r:
# we have not found our material in self.materials dict :-(
# we're going to add a user-defined temporary material: a document material
FreeCAD.Console.PrintMessage(
"Previously used material card cannot be found in material directories. "
"Add document material.\n"
)
self.card_path_r = '_Document_Reinforcement_Material'
self.materials[self.card_path_r] = self.material_r
self.parameterWidget.cb_materials_r.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_r,
self.card_path_r
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# set the current material in the cb widget
self.choose_material_r(index)
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Previously used material card was found in material directories. "
"We will use this material.\n"
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# print(index)
# fill input fields and set the current material in the cb widget
self.choose_material_r(index)
# set up the form
self.form = self.parameterWidget
# leave task panel ***************************************************************************
def accept(self):
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(self.material_m) is True and checkunits(self.material_r) is True:
self.obj.Material = self.material_m
self.obj.Reinforcement = self.material_r
else:
error_message = (
'Due to some wrong material quantity units in the changed '
'material data, the task panel changes where not accepted.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
self.recompute_and_set_back_all()
return True
def reject(self):
self.recompute_and_set_back_all()
return True
def recompute_and_set_back_all(self):
guidoc = FreeCADGui.getDocument(self.obj.Document)
guidoc.Document.recompute()
guidoc.resetEdit()
self.output_obj_mat_param()
def output_obj_mat_param(self):
self.print_mat_dict(self.obj.Material)
self.print_mat_dict(self.obj.Reinforcement)
print('\n')
def print_mat_dict(self, mat_dict):
if 'Name' in mat_dict:
print('Material: {}'.format(mat_dict['Name']))
else:
print('Matrix material: no Name')
for key in mat_dict:
print(' {}: {}'.format(key, mat_dict[key]))
# choose material card ***********************************************************************
def get_material_card(self, material):
for a_mat in self.materials:
unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items())
# print(a_mat + ' --> unmatched_items = ' + str(len(unmatched_items)))
if len(unmatched_items) < 4:
FreeCAD.Console.PrintLog('{}\n'.format(unmatched_items))
if len(unmatched_items) == 0:
return a_mat
return ""
def choose_material_m(self, index):
if index < 0:
return
# get the whole card path
self.card_path_m = self.parameterWidget.cb_materials_m.itemData(index)
FreeCAD.Console.PrintMessage(
'choose_material in FEM material task panel:\n'
' {}\n'.format(self.card_path_m)
)
self.material_m = self.materials[self.card_path_m]
self.parameterWidget.cb_materials_m.setCurrentIndex(index)
gen_mat_desc = ""
gen_mat_name = ""
if 'Description' in self.material_m:
gen_mat_desc = self.material_m['Description']
if 'Name' in self.material_m:
gen_mat_name = self.material_m['Name']
self.parameterWidget.l_description_m.setText(gen_mat_desc)
self.parameterWidget.l_name_m.setText(gen_mat_name)
def choose_material_r(self, index):
if index < 0:
return
# get the whole card path
self.card_path_r = self.parameterWidget.cb_materials_r.itemData(index)
FreeCAD.Console.PrintMessage(
'choose_material in FEM material task panel:\n'
' {}\n'.format(self.card_path_r)
)
self.material_r = self.materials[self.card_path_r]
self.parameterWidget.cb_materials_r.setCurrentIndex(index)
gen_mat_desc = ""
gen_mat_name = ""
if 'Description' in self.material_r:
gen_mat_desc = self.material_r['Description']
if 'Name' in self.material_r:
gen_mat_name = self.material_r['Name']
self.parameterWidget.l_description_r.setText(gen_mat_desc)
self.parameterWidget.l_name_r.setText(gen_mat_name)
# transient material is needed if the user changed mat parameter by the mat editor
def set_transient_material_m(self):
self.card_path_m = '_Transient_Matrix_Material'
self.materials[self.card_path_m] = self.material_m # = the current matrix mat dict
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
self.choose_material_m(index)
def add_transient_material_m(self):
self.has_transient_mat_m = True
self.card_path_m = '_Transient_Matrix_Material'
self.parameterWidget.cb_materials_m.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_m,
self.card_path_m
)
self.set_transient_material_m()
def set_transient_material_r(self):
self.card_path_r = '_Transient_Reinforcement_Material'
self.materials[self.card_path_r] = self.material_r # = the current reinforced mat dict
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
self.choose_material_r(index)
def add_transient_material_r(self):
self.has_transient_mat_r = True
self.card_path_r = '_Transient_Reinforcement_Material'
self.parameterWidget.cb_materials_r.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path_r,
self.card_path_r
)
self.set_transient_material_r()
# edit material parameter ********************************************************************
# TODO, also all mat parameter checks should be moved to material editor
# and mat parameter checks should be done on analysis precheck in according to the analysis
# should be checked if all needed parameter are defined and have all right values and units
def edit_material_m(self):
# opens the material editor to choose a material or edit material params
import MaterialEditor
if self.card_path_m not in self.cards:
FreeCAD.Console.PrintLog(
'Card path not in cards, material dict will be used to open Material Editor.\n'
)
new_material_params = MaterialEditor.editMaterial(material=self.material_m)
else:
new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_m)
# material editor returns the mat_dict only, not a card_path
# if the material editor was canceled a empty dict will be returned
# do not change the self.material
# check if dict is not empty (do not use 'is True')
if new_material_params:
# check material quantity units
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(new_material_params) is True:
self.material_m = new_material_params
self.card_path_m = self.get_material_card(self.material_m)
FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_m))
if not self.card_path_m:
FreeCAD.Console.PrintMessage(
"Material card chosen by the material editor "
"was not found in material directories.\n"
"Either the card does not exist or some material "
"parameter where changed in material editor.\n"
)
if self.has_transient_mat_m is False:
self.add_transient_material_m()
else:
self.set_transient_material_m()
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Material card chosen by the material editor "
"was found in material directories. "
"The found material card will be used.\n"
)
index = self.parameterWidget.cb_materials_m.findData(self.card_path_m)
# print(index)
# set the current material in the cb widget
self.choose_material_m(index)
else:
error_message = (
'Due to some wrong material quantity units in data passed '
'by the material editor, the material data was not changed.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
else:
FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n')
def edit_material_r(self):
# opens the material editor to choose a material or edit material params
import MaterialEditor
if self.card_path_r not in self.cards:
FreeCAD.Console.PrintLog(
'Card path not in cards, material dict will be used to open Material Editor.\n'
)
new_material_params = MaterialEditor.editMaterial(material=self.material_r)
else:
new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_r)
# material editor returns the mat_dict only, not a card_path
# if the material editor was canceled a empty dict will be returned
# do not change the self.material
# check if dict is not empty (do not use 'is True')
if new_material_params:
# check material quantity units
from materialtools.cardutils import check_mat_units as checkunits
if checkunits(new_material_params) is True:
self.material_r = new_material_params
self.card_path_r = self.get_material_card(self.material_r)
FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_r))
if not self.card_path_r:
FreeCAD.Console.PrintMessage(
"Material card chosen by the material editor "
"was not found in material directories.\n"
"Either the card does not exist or some material "
"parameter where changed in material editor.\n"
)
if self.has_transient_mat_r is False:
self.add_transient_material_r()
else:
self.set_transient_material_r()
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintLog(
"Material card chosen by the material editor "
"was found in material directories. "
"The found material card will be used.\n"
)
index = self.parameterWidget.cb_materials_r.findData(self.card_path_r)
# print(index)
# set the current material in the cb widget
self.choose_material_r(index)
else:
error_message = (
'Due to some wrong material quantity units in data passed '
'by the material editor, the material data was not changed.\n'
)
FreeCAD.Console.PrintError(error_message)
QtGui.QMessageBox.critical(None, "Material data not changed", error_message)
else:
FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n')
# fill the combo box with cards **************************************************************
def add_cards_to_combo_boxes(self):
# fill comboboxes, in combo box the card name is used not the material name
self.parameterWidget.cb_materials_m.clear()
self.parameterWidget.cb_materials_r.clear()
mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Cards")
sort_by_resources = mat_prefs.GetBool("SortByResources", False)
card_name_list = [] # [ [card_name, card_path, icon_path], ... ]
if sort_by_resources is True:
for a_path in sorted(self.materials.keys()):
card_name_list.append([self.cards[a_path], a_path, self.icons[a_path]])
else:
card_names_tmp = {}
for path, name in self.cards.items():
card_names_tmp[name] = path
for a_name in sorted(card_names_tmp.keys()):
a_path = card_names_tmp[a_name]
card_name_list.append([a_name, a_path, self.icons[a_path]])
for mat in card_name_list:
self.parameterWidget.cb_materials_m.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1])
self.parameterWidget.cb_materials_r.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1])
# the whole card path is added to the combo box to make it unique
# see def choose_material:
# for assignment of self.card_path the path form the parameterWidget ist used