FEM: task panels, move them into the view provider modules
This commit is contained in:
committed by
Yorik van Havre
parent
b030184f89
commit
bb8fdeccc7
@@ -155,16 +155,6 @@ SET(FemTestsElmer_SRCS
|
||||
|
||||
SET(FemGuiScripts_SRCS
|
||||
PyGui/__init__.py
|
||||
PyGui/_TaskPanelFemElementFluid1D.py
|
||||
PyGui/_TaskPanelFemElementGeometry1D.py
|
||||
PyGui/_TaskPanelFemElementGeometry2D.py
|
||||
PyGui/_TaskPanelFemMaterial.py
|
||||
PyGui/_TaskPanelFemMeshBoundaryLayer.py
|
||||
PyGui/_TaskPanelFemMeshGmsh.py
|
||||
PyGui/_TaskPanelFemMeshGroup.py
|
||||
PyGui/_TaskPanelFemMeshRegion.py
|
||||
PyGui/_TaskPanelFemResultShow.py
|
||||
PyGui/_TaskPanelFemSolverCalculix.py
|
||||
PyGui/_TaskPanelFemSolverControl.py
|
||||
PyGui/_ViewProviderFemConstraintBodyHeatSource.py
|
||||
PyGui/_ViewProviderFemConstraintElectrostaticPotential.py
|
||||
|
||||
@@ -1,416 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Ofentse Kgoa <kgoaot@eskom.co.za> *
|
||||
# * Based on the FemElementGeometry1D by Bernd Hahnebach *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemElementFluid1D"
|
||||
__author__ = "Ofentse Kgoa"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemElementFluid1D
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
import PyObjects._FemElementFluid1D
|
||||
|
||||
|
||||
class _TaskPanelFemElementFluid1D:
|
||||
'''The TaskPanel for editing References property of FemElementFluid1D objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementFluid1D.ui")
|
||||
QtCore.QObject.connect(self.form.btn_add, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
QtCore.QObject.connect(self.form.btn_remove, QtCore.SIGNAL("clicked()"), self.remove_reference)
|
||||
QtCore.QObject.connect(self.form.cb_section_type, QtCore.SIGNAL("activated(int)"), self.sectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.cb_liquid_section_type, QtCore.SIGNAL("activated(int)"), self.liquidsectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.if_manning_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.manning_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_manning_radius, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.manning_radius_changed)
|
||||
QtCore.QObject.connect(self.form.sb_manning_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.manning_coefficient_changed)
|
||||
QtCore.QObject.connect(self.form.if_enlarge_area1, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.enlarge_area1_changed)
|
||||
QtCore.QObject.connect(self.form.if_enlarge_area2, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.enlarge_area2_changed)
|
||||
QtCore.QObject.connect(self.form.if_contract_area1, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.contract_area1_changed)
|
||||
QtCore.QObject.connect(self.form.if_contract_area2, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.contract_area2_changed)
|
||||
QtCore.QObject.connect(self.form.if_inletpressure, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.inlet_pressure_changed)
|
||||
QtCore.QObject.connect(self.form.if_outletpressure, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.outlet_pressure_changed)
|
||||
QtCore.QObject.connect(self.form.if_inletflowrate, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.inlet_flowrate_changed)
|
||||
QtCore.QObject.connect(self.form.if_outletflowrate, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.outlet_flowrate_changed)
|
||||
QtCore.QObject.connect(self.form.gb_inletpressure, QtCore.SIGNAL("clicked(bool)"), self.inlet_pressure_active)
|
||||
QtCore.QObject.connect(self.form.gb_outletpressure, QtCore.SIGNAL("clicked(bool)"), self.outlet_pressure_active)
|
||||
QtCore.QObject.connect(self.form.gb_inletflowrate, QtCore.SIGNAL("clicked(bool)"), self.inlet_flowrate_active)
|
||||
QtCore.QObject.connect(self.form.gb_outletflowrate, QtCore.SIGNAL("clicked(bool)"), self.outlet_flowrate_active)
|
||||
QtCore.QObject.connect(self.form.if_entrance_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.entrance_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_entrance_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.entrance_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_diaphragm_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.diaphragm_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_diaphragm_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.diaphragm_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_bend_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.bend_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bradius_pdiameter, QtCore.SIGNAL("valueChanged(double)"), self.bradius_pdiameter_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bend_angle, QtCore.SIGNAL("valueChanged(double)"), self.bend_angle_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bend_loss_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.bend_loss_coefficient_changed)
|
||||
QtCore.QObject.connect(self.form.if_gatevalve_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.gatevalve_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.sb_gatevalve_closing_coeff, QtCore.SIGNAL("valueChanged(double)"), self.gatevalve_closing_coeff_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_radius, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_radius_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_grain_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_grain_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.sb_colebrooke_form_factor, QtCore.SIGNAL("valueChanged(double)"), self.colebrooke_form_factor_changed)
|
||||
QtCore.QObject.connect(self.form.tw_pump_characteristics, QtCore.SIGNAL("cellChanged(int, int)"), self.pump_characteristics_changed)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
self.form.cb_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_fluid_types)
|
||||
self.form.cb_liquid_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_liquid_types)
|
||||
self.form.cb_gas_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_gas_types)
|
||||
self.form.cb_channel_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_channel_types)
|
||||
|
||||
self.get_fluidsection_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_fluidsection_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_fluidsection_props(self):
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
self.SectionType = self.obj.SectionType
|
||||
self.LiquidSectionType = self.obj.LiquidSectionType
|
||||
self.ManningArea = self.obj.ManningArea
|
||||
self.ManningRadius = self.obj.ManningRadius
|
||||
self.ManningCoefficient = self.obj.ManningCoefficient
|
||||
self.EnlargeArea1 = self.obj.EnlargeArea1
|
||||
self.EnlargeArea2 = self.obj.EnlargeArea2
|
||||
self.ContractArea1 = self.obj.ContractArea1
|
||||
self.ContractArea2 = self.obj.ContractArea2
|
||||
self.OutletPressure = self.obj.OutletPressure
|
||||
self.InletPressure = self.obj.InletPressure
|
||||
self.OutletFlowRate = self.obj.OutletFlowRate
|
||||
self.InletFlowRate = self.obj.InletFlowRate
|
||||
self.OutletPressureActive = self.obj.OutletPressureActive
|
||||
self.InletPressureActive = self.obj.InletPressureActive
|
||||
self.OutletFlowRateActive = self.obj.OutletFlowRateActive
|
||||
self.InletFlowRateActive = self.obj.InletFlowRateActive
|
||||
self.EntrancePipeArea = self.obj.EntrancePipeArea
|
||||
self.EntranceArea = self.obj.EntranceArea
|
||||
self.DiaphragmPipeArea = self.obj.DiaphragmPipeArea
|
||||
self.DiaphragmArea = self.obj.DiaphragmArea
|
||||
self.BendPipeArea = self.obj.BendPipeArea
|
||||
self.BendRadiusDiameter = self.obj.BendRadiusDiameter
|
||||
self.BendAngle = self.obj.BendAngle
|
||||
self.BendLossCoefficient = self.obj.BendLossCoefficient
|
||||
self.GateValvePipeArea = self.obj.GateValvePipeArea
|
||||
self.GateValveClosingCoeff = self.obj.GateValveClosingCoeff
|
||||
self.ColebrookeArea = self.obj.ColebrookeArea
|
||||
self.ColebrookeRadius = self.obj.ColebrookeRadius
|
||||
self.ColebrookeGrainDiameter = self.obj.ColebrookeGrainDiameter
|
||||
self.ColebrookeFormFactor = self.obj.ColebrookeFormFactor
|
||||
self.PumpFlowRate = self.obj.PumpFlowRate
|
||||
self.PumpHeadLoss = self.obj.PumpHeadLoss
|
||||
|
||||
def set_fluidsection_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.LiquidSectionType = self.LiquidSectionType
|
||||
self.obj.SectionType = self.SectionType
|
||||
self.obj.ManningArea = self.ManningArea
|
||||
self.obj.ManningRadius = self.ManningRadius
|
||||
self.obj.ManningCoefficient = self.ManningCoefficient
|
||||
self.obj.EnlargeArea1 = self.EnlargeArea1
|
||||
self.obj.EnlargeArea2 = self.EnlargeArea2
|
||||
self.obj.ContractArea1 = self.ContractArea1
|
||||
self.obj.ContractArea2 = self.ContractArea2
|
||||
self.obj.OutletPressure = self.OutletPressure
|
||||
self.obj.InletPressure = self.InletPressure
|
||||
self.obj.OutletFlowRate = self.OutletFlowRate
|
||||
self.obj.InletFlowRate = self.InletFlowRate
|
||||
self.obj.OutletPressureActive = self.OutletPressureActive
|
||||
self.obj.InletPressureActive = self.InletPressureActive
|
||||
self.obj.OutletFlowRateActive = self.OutletFlowRateActive
|
||||
self.obj.InletFlowRateActive = self.InletFlowRateActive
|
||||
self.obj.EntrancePipeArea = self.EntrancePipeArea
|
||||
self.obj.EntranceArea = self.EntranceArea
|
||||
self.obj.DiaphragmPipeArea = self.DiaphragmPipeArea
|
||||
self.obj.DiaphragmArea = self.DiaphragmArea
|
||||
self.obj.BendPipeArea = self.BendPipeArea
|
||||
self.obj.BendRadiusDiameter = self.BendRadiusDiameter
|
||||
self.obj.BendAngle = self.BendAngle
|
||||
self.obj.BendLossCoefficient = self.BendLossCoefficient
|
||||
self.obj.GateValvePipeArea = self.GateValvePipeArea
|
||||
self.obj.GateValveClosingCoeff = self.GateValveClosingCoeff
|
||||
self.obj.ColebrookeArea = self.ColebrookeArea
|
||||
self.obj.ColebrookeRadius = self.ColebrookeRadius
|
||||
self.obj.ColebrookeGrainDiameter = self.ColebrookeGrainDiameter
|
||||
self.obj.ColebrookeFormFactor = self.ColebrookeFormFactor
|
||||
self.obj.PumpFlowRate = self.PumpFlowRate
|
||||
self.obj.PumpHeadLoss = self.PumpHeadLoss
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
index_sectiontype = self.form.cb_section_type.findText(self.SectionType)
|
||||
self.form.cb_section_type.setCurrentIndex(index_sectiontype)
|
||||
self.form.sw_section_type.setCurrentIndex(index_sectiontype)
|
||||
index_liquidsectiontype = self.form.cb_liquid_section_type.findText(self.LiquidSectionType)
|
||||
self.form.cb_liquid_section_type.setCurrentIndex(index_liquidsectiontype)
|
||||
self.form.sw_liquid_section_type.setCurrentIndex(index_liquidsectiontype)
|
||||
self.form.if_manning_area.setText(self.ManningArea.UserString)
|
||||
self.form.if_manning_radius.setText(self.ManningRadius.UserString)
|
||||
self.form.sb_manning_coefficient.setValue(self.ManningCoefficient)
|
||||
self.form.if_enlarge_area1.setText(self.EnlargeArea1.UserString)
|
||||
self.form.if_enlarge_area2.setText(self.EnlargeArea2.UserString)
|
||||
self.form.if_contract_area1.setText(self.ContractArea1.UserString)
|
||||
self.form.if_contract_area2.setText(self.ContractArea2.UserString)
|
||||
self.form.if_inletpressure.setText(FreeCAD.Units.Quantity(1000 * self.InletPressure, FreeCAD.Units.Pressure).UserString)
|
||||
self.form.if_outletpressure.setText(FreeCAD.Units.Quantity(1000 * self.OutletPressure, FreeCAD.Units.Pressure).UserString)
|
||||
self.form.if_inletflowrate.setText(str(self.InletFlowRate))
|
||||
self.form.if_outletflowrate.setText(str(self.OutletFlowRate))
|
||||
self.form.gb_inletpressure.setChecked(self.InletPressureActive)
|
||||
self.form.gb_outletpressure.setChecked(self.OutletPressureActive)
|
||||
self.form.gb_inletflowrate.setChecked(self.InletFlowRateActive)
|
||||
self.form.gb_outletflowrate.setChecked(self.OutletFlowRateActive)
|
||||
self.form.if_entrance_pipe_area.setText(self.EntrancePipeArea.UserString)
|
||||
self.form.if_entrance_area.setText(self.EntranceArea.UserString)
|
||||
self.form.if_diaphragm_pipe_area.setText(self.DiaphragmPipeArea.UserString)
|
||||
self.form.if_diaphragm_area.setText(self.DiaphragmArea.UserString)
|
||||
self.form.if_bend_pipe_area.setText(self.BendPipeArea.UserString)
|
||||
self.form.sb_bradius_pdiameter.setValue(self.BendRadiusDiameter)
|
||||
self.form.sb_bend_angle.setValue(self.BendAngle)
|
||||
self.form.sb_bend_loss_coefficient.setValue(self.BendLossCoefficient)
|
||||
self.form.if_gatevalve_pipe_area.setText(self.GateValvePipeArea.UserString)
|
||||
self.form.sb_gatevalve_closing_coeff.setValue(self.GateValveClosingCoeff)
|
||||
self.form.if_colebrooke_pipe_area.setText(self.ColebrookeArea.UserString)
|
||||
self.form.if_colebrooke_radius.setText(self.ColebrookeRadius.UserString)
|
||||
self.form.if_colebrooke_grain_diameter.setText(self.ColebrookeGrainDiameter.UserString)
|
||||
self.form.sb_colebrooke_form_factor.setValue(self.ColebrookeFormFactor)
|
||||
for i in range(len(self.PumpFlowRate)):
|
||||
self.form.tw_pump_characteristics.setItem(i, 0, QtGui.QTableWidgetItem(str(self.PumpFlowRate[i])))
|
||||
self.form.tw_pump_characteristics.setItem(i, 1, QtGui.QTableWidgetItem(str(self.PumpHeadLoss[i])))
|
||||
self.rebuild_list_References()
|
||||
|
||||
def sectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_section_type.setCurrentIndex(index)
|
||||
self.form.sw_section_type.setCurrentIndex(index)
|
||||
self.SectionType = str(self.form.cb_section_type.itemText(index)) # form returns unicode
|
||||
|
||||
def liquidsectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_liquid_section_type.setCurrentIndex(index)
|
||||
self.form.sw_liquid_section_type.setCurrentIndex(index)
|
||||
self.LiquidSectionType = str(self.form.cb_liquid_section_type.itemText(index)) # form returns unicode
|
||||
|
||||
def manning_area_changed(self, base_quantity_value):
|
||||
self.ManningArea = base_quantity_value
|
||||
|
||||
def manning_radius_changed(self, base_quantity_value):
|
||||
self.ManningRadius = base_quantity_value
|
||||
|
||||
def manning_coefficient_changed(self, base_quantity_value):
|
||||
self.ManningCoefficient = base_quantity_value
|
||||
|
||||
def enlarge_area1_changed(self, base_quantity_value):
|
||||
self.EnlargeArea1 = base_quantity_value
|
||||
|
||||
def enlarge_area2_changed(self, base_quantity_value):
|
||||
self.EnlargeArea2 = base_quantity_value
|
||||
|
||||
def contract_area1_changed(self, base_quantity_value):
|
||||
self.ContractArea1 = base_quantity_value
|
||||
|
||||
def contract_area2_changed(self, base_quantity_value):
|
||||
self.ContractArea2 = base_quantity_value
|
||||
|
||||
def inlet_pressure_changed(self, base_quantity_value):
|
||||
self.InletPressure = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("MPa"))
|
||||
|
||||
def outlet_pressure_changed(self, base_quantity_value):
|
||||
self.OutletPressure = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("MPa"))
|
||||
|
||||
def inlet_flowrate_changed(self, base_quantity_value):
|
||||
self.InletFlowRate = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("kg/s"))
|
||||
|
||||
def outlet_flowrate_changed(self, base_quantity_value):
|
||||
self.OutletFlowRate = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("kg/s"))
|
||||
|
||||
def inlet_pressure_active(self, active):
|
||||
self.InletPressureActive = active
|
||||
|
||||
def outlet_pressure_active(self, active):
|
||||
self.OutletPressureActive = active
|
||||
|
||||
def inlet_flowrate_active(self, active):
|
||||
self.InletFlowRateActive = active
|
||||
|
||||
def outlet_flowrate_active(self, active):
|
||||
self.OutletFlowRateActive = active
|
||||
|
||||
def entrance_pipe_area_changed(self, base_quantity_value):
|
||||
self.EntrancePipeArea = base_quantity_value
|
||||
|
||||
def entrance_area_changed(self, base_quantity_value):
|
||||
self.EntranceArea = base_quantity_value
|
||||
|
||||
def diaphragm_pipe_area_changed(self, base_quantity_value):
|
||||
self.DiaphragmPipeArea = base_quantity_value
|
||||
|
||||
def diaphragm_area_changed(self, base_quantity_value):
|
||||
self.DiaphragmArea = base_quantity_value
|
||||
|
||||
def bend_pipe_area_changed(self, base_quantity_value):
|
||||
self.BendPipeArea = base_quantity_value
|
||||
|
||||
def bradius_pdiameter_changed(self, base_quantity_value):
|
||||
self.BendRadiusDiameter = base_quantity_value
|
||||
|
||||
def bend_angle_changed(self, base_quantity_value):
|
||||
self.BendAngle = base_quantity_value
|
||||
|
||||
def bend_loss_coefficient_changed(self, base_quantity_value):
|
||||
self.BendLossCoefficient = base_quantity_value
|
||||
|
||||
def gatevalve_pipe_area_changed(self, base_quantity_value):
|
||||
self.GateValvePipeArea = base_quantity_value
|
||||
|
||||
def gatevalve_closing_coeff_changed(self, base_quantity_value):
|
||||
self.GateValveClosingCoeff = base_quantity_value
|
||||
|
||||
def colebrooke_pipe_area_changed(self, base_quantity_value):
|
||||
self.ColebrookeArea = base_quantity_value
|
||||
|
||||
def colebrooke_radius_changed(self, base_quantity_value):
|
||||
self.ColebrookeRadius = base_quantity_value
|
||||
|
||||
def colebrooke_grain_diameter_changed(self, base_quantity_value):
|
||||
self.ColebrookeGrainDiameter = base_quantity_value
|
||||
|
||||
def colebrooke_form_factor_changed(self, base_quantity_value):
|
||||
self.ColebrookeFormFactor = base_quantity_value
|
||||
|
||||
def pump_characteristics_changed(self, row, column):
|
||||
if column == 0:
|
||||
self.PumpFlowRate[row] = float(self.form.tw_pump_characteristics.item(row, column).text())
|
||||
else:
|
||||
self.PumpHeadLoss[row] = float(self.form.tw_pump_characteristics.item(row, column).text())
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Edges by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Edge':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,215 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2015 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemElementGeometry1D"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemElementGeometry1D
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
import PyObjects._FemElementGeometry1D
|
||||
|
||||
|
||||
class _TaskPanelFemElementGeometry1D:
|
||||
'''The TaskPanel for editing References property of FemElementGeometry1D objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementGeometry1D.ui")
|
||||
QtCore.QObject.connect(self.form.cb_crosssectiontype, QtCore.SIGNAL("activated(int)"), self.sectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.if_rec_height, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.rec_height_changed)
|
||||
QtCore.QObject.connect(self.form.if_rec_width, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.rec_width_changed)
|
||||
QtCore.QObject.connect(self.form.if_circ_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.circ_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.if_pipe_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.pipe_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.if_pipe_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.pipe_thickness_changed)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.form.cb_crosssectiontype.addItems(PyObjects._FemElementGeometry1D._FemElementGeometry1D.known_beam_types) # it is inside the class thus double _FemElementGeometry1D
|
||||
|
||||
self.get_beamsection_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_beamsection_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_beamsection_props(self):
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
self.SectionType = self.obj.SectionType
|
||||
self.RectHeight = self.obj.RectHeight
|
||||
self.RectWidth = self.obj.RectWidth
|
||||
self.CircDiameter = self.obj.CircDiameter
|
||||
self.PipeDiameter = self.obj.PipeDiameter
|
||||
self.PipeThickness = self.obj.PipeThickness
|
||||
|
||||
def set_beamsection_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.SectionType = self.SectionType
|
||||
self.obj.RectHeight = self.RectHeight
|
||||
self.obj.RectWidth = self.RectWidth
|
||||
self.obj.CircDiameter = self.CircDiameter
|
||||
self.obj.PipeDiameter = self.PipeDiameter
|
||||
self.obj.PipeThickness = self.PipeThickness
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
index_crosssectiontype = self.form.cb_crosssectiontype.findText(self.SectionType)
|
||||
self.form.cb_crosssectiontype.setCurrentIndex(index_crosssectiontype)
|
||||
self.form.if_rec_height.setText(self.RectHeight.UserString)
|
||||
self.form.if_rec_width.setText(self.RectWidth.UserString)
|
||||
self.form.if_circ_diameter.setText(self.CircDiameter.UserString)
|
||||
self.form.if_pipe_diameter.setText(self.PipeDiameter.UserString)
|
||||
self.form.if_pipe_thickness.setText(self.PipeThickness.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def sectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_crosssectiontype.setCurrentIndex(index)
|
||||
self.SectionType = str(self.form.cb_crosssectiontype.itemText(index)) # form returns unicode
|
||||
|
||||
def rec_height_changed(self, base_quantity_value):
|
||||
self.RectHeight = base_quantity_value
|
||||
|
||||
def rec_width_changed(self, base_quantity_value):
|
||||
self.RectWidth = base_quantity_value
|
||||
|
||||
def circ_diameter_changed(self, base_quantity_value):
|
||||
self.CircDiameter = base_quantity_value
|
||||
|
||||
def pipe_diameter_changed(self, base_quantity_value):
|
||||
self.PipeDiameter = base_quantity_value
|
||||
|
||||
def pipe_thickness_changed(self, base_quantity_value):
|
||||
self.PipeThickness = base_quantity_value
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Edges by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Edge':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,173 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2015 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemElementGeometry2D"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package FemElementGeometry2D
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _TaskPanelFemElementGeometry2D:
|
||||
'''The TaskPanel for editing References property of FemElementGeometry2D objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementGeometry2D.ui")
|
||||
QtCore.QObject.connect(self.form.if_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.thickness_changed)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_shellthickness_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_shellthickness_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_shellthickness_props(self):
|
||||
self.thickness = self.obj.Thickness
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_shellthickness_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.Thickness = self.thickness
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_thickness.setText(self.thickness.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def thickness_changed(self, base_quantity_value):
|
||||
self.thickness = base_quantity_value
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Faces by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Face':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,642 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2013 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMaterial"
|
||||
__author__ = "Juergen Riegel, Bernd Hahnebach, Qingfeng Xia"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMaterial
|
||||
# \ingroup FEM
|
||||
|
||||
import sys
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from FreeCAD import Units
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtGui import QFileDialog, QMessageBox
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
unicode = str
|
||||
|
||||
|
||||
class _TaskPanelFemMaterial:
|
||||
'''The editmode TaskPanel for FemMaterial objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces and Edges by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
self.material = self.obj.Material
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMaterial.ui")
|
||||
QtCore.QObject.connect(self.form.pushButton_MatWeb, QtCore.SIGNAL("clicked()"), self.goto_MatWeb)
|
||||
QtCore.QObject.connect(self.form.pushButton_saveas, QtCore.SIGNAL("clicked()"), self.export_material)
|
||||
QtCore.QObject.connect(self.form.cb_materials, QtCore.SIGNAL("activated(int)"), self.choose_material)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
# basic properties must be provided
|
||||
QtCore.QObject.connect(self.form.input_fd_density, QtCore.SIGNAL("valueChanged(double)"), self.density_changed)
|
||||
# mechanical properties
|
||||
QtCore.QObject.connect(self.form.input_fd_young_modulus, QtCore.SIGNAL("valueChanged(double)"), self.ym_changed)
|
||||
QtCore.QObject.connect(self.form.spinBox_poisson_ratio, QtCore.SIGNAL("valueChanged(double)"), self.pr_changed)
|
||||
# thermal properties
|
||||
QtCore.QObject.connect(self.form.input_fd_thermal_conductivity, QtCore.SIGNAL("valueChanged(double)"), self.tc_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_expansion_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.tec_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_specific_heat, QtCore.SIGNAL("valueChanged(double)"), self.sh_changed)
|
||||
# fluidic properties, only volumetric thermal expansion coeff makes sense
|
||||
QtCore.QObject.connect(self.form.input_fd_kinematic_viscosity, QtCore.SIGNAL("valueChanged(double)"), self.kinematic_viscosity_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_vol_expansion_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.vtec_changed)
|
||||
|
||||
# hide some groupBox according to material category
|
||||
self.form.label_category.setText(self.obj.Category)
|
||||
if self.obj.Category == 'Fluid':
|
||||
self.form.groupBox_mechanical.setVisible(0)
|
||||
self.form.label_expansion_coefficient.setVisible(0)
|
||||
self.form.input_fd_expansion_coefficient.setVisible(0)
|
||||
else:
|
||||
self.form.groupBox_fluidic.setVisible(0)
|
||||
self.form.label_vol_expansion_coefficient.setVisible(0)
|
||||
self.form.input_fd_vol_expansion_coefficient.setVisible(0)
|
||||
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.import_materials()
|
||||
previous_mat_path = self.get_material_path(self.material)
|
||||
if not previous_mat_path:
|
||||
material_name = self.get_material_name(self.material)
|
||||
if material_name != 'None':
|
||||
FreeCAD.Console.PrintMessage("Previously used material cannot be found in material directories. Using transient material.\n")
|
||||
self.add_transient_material(self.material)
|
||||
index = self.form.cb_materials.findData(material_name)
|
||||
else:
|
||||
if not self.material:
|
||||
index = self.form.cb_materials.findText(material_name)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("None material was previously used. Reload values.\n")
|
||||
self.add_transient_material(self.material)
|
||||
index = self.form.cb_materials.findData(material_name)
|
||||
self.choose_material(index)
|
||||
else:
|
||||
index = self.form.cb_materials.findData(previous_mat_path)
|
||||
self.choose_material(index)
|
||||
self.has_equal_references_shape_types()
|
||||
self.rebuild_list_References()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
# print(self.material)
|
||||
self.remove_active_sel_server()
|
||||
if self.has_equal_references_shape_types():
|
||||
self.obj.Material = self.material
|
||||
self.obj.References = self.references
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
doc.Document.recompute()
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.remove_active_sel_server()
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
|
||||
def remove_active_sel_server(self):
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def has_equal_references_shape_types(self):
|
||||
import femmesh.meshtools as FemMeshTools
|
||||
ref_shty = ''
|
||||
for ref in self.references:
|
||||
r = FemMeshTools.get_element(ref[0], ref[1]) # the method getElement(element) does not return Solid elements
|
||||
# print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1])
|
||||
if not ref_shty:
|
||||
ref_shty = r.ShapeType
|
||||
if r.ShapeType != ref_shty:
|
||||
message = 'Multiple shape types are not allowed in the reference list.\n'
|
||||
FreeCAD.Console.PrintError(message)
|
||||
QMessageBox.critical(None, "Multiple ShapeTypes not allowed", message)
|
||||
return False
|
||||
return True
|
||||
|
||||
def goto_MatWeb(self):
|
||||
import webbrowser
|
||||
webbrowser.open("http://matweb.com")
|
||||
|
||||
def check_material_keys(self):
|
||||
if 'Density' in self.material:
|
||||
if 'Density' not in str(Units.Unit(self.material['Density'])):
|
||||
print('Density in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['Density'] = '0 kg/m^3'
|
||||
else:
|
||||
print('Density not found in material data of: ' + self.material['Name'])
|
||||
self.material['Density'] = '0 kg/m^3'
|
||||
if self.obj.Category == 'Solid':
|
||||
# mechanical properties
|
||||
if 'YoungsModulus' in self.material:
|
||||
if 'Pressure' not in str(Units.Unit(self.material['YoungsModulus'])): # unit type of YoungsModulus is Pressure
|
||||
print('YoungsModulus in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['YoungsModulus'] = '0 MPa'
|
||||
else:
|
||||
print('YoungsModulus not found in material data of: ' + self.material['Name'])
|
||||
self.material['YoungsModulus'] = '0 MPa'
|
||||
if 'PoissonRatio' not in self.material: # PoissonRatio does not have a unit, we do not gone check for a unit
|
||||
print('PoissonRatio not found in material data of: ' + self.material['Name'])
|
||||
self.material['PoissonRatio'] = '0'
|
||||
if self.obj.Category == 'Fluid':
|
||||
# Fluidic properties
|
||||
if 'KinematicViscosity' in self.material:
|
||||
if 'KinematicViscosity' not in str(Units.Unit(self.material['KinematicViscosity'])):
|
||||
print('KinematicViscosity in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['KinematicViscosity'] = '0 m^2/s'
|
||||
else:
|
||||
print('KinematicViscosity not found in material data of: ' + self.material['Name'])
|
||||
self.material['KinematicViscosity'] = '0 m^2/s'
|
||||
if 'VolumetricThermalExpansionCoefficient' in self.material:
|
||||
if 'ThermalExpansionCoefficient' not in str(Units.Unit(self.material['VolumetricThermalExpansionCoefficient'])): # unit type of VolumetricThermalExpansionCoefficient is ThermalExpansionCoefficient
|
||||
print('VolumetricThermalExpansionCoefficient in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
|
||||
else:
|
||||
print('VolumetricThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
|
||||
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
|
||||
# Thermal properties
|
||||
if 'ThermalConductivity' in self.material:
|
||||
if 'ThermalConductivity' not in str(Units.Unit(self.material['ThermalConductivity'])):
|
||||
print('ThermalConductivity in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['ThermalConductivity'] = '0 W/m/K'
|
||||
else:
|
||||
print('ThermalConductivity not found in material data of: ' + self.material['Name'])
|
||||
self.material['ThermalConductivity'] = '0 W/m/K'
|
||||
if 'ThermalExpansionCoefficient' in self.material:
|
||||
if 'ThermalExpansionCoefficient' not in str(Units.Unit(self.material['ThermalExpansionCoefficient'])):
|
||||
print('ThermalExpansionCoefficient in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
|
||||
else:
|
||||
print('ThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
|
||||
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
|
||||
if 'SpecificHeat' in self.material:
|
||||
if 'SpecificHeat' not in str(Units.Unit(self.material['SpecificHeat'])):
|
||||
print('SpecificHeat in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['SpecificHeat'] = '0 J/kg/K'
|
||||
else:
|
||||
print('SpecificHeat not found in material data of: ' + self.material['Name'])
|
||||
self.material['SpecificHeat'] = '0 J/kg/K'
|
||||
|
||||
def ym_changed(self, value):
|
||||
# FreeCADs standard unit for stress is kPa
|
||||
old_ym = Units.Quantity(self.material['YoungsModulus']).getValueAs("kPa")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_ym) / value < 1 + variation):
|
||||
# YoungsModulus has changed
|
||||
material = self.material
|
||||
material['YoungsModulus'] = unicode(value) + " kPa"
|
||||
self.material = material
|
||||
|
||||
def density_changed(self, value):
|
||||
# FreeCADs standard unit for density is kg/mm^3
|
||||
old_density = Units.Quantity(self.material['Density']).getValueAs("kg/m^3")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_density) / value < 1 + variation):
|
||||
# density has changed
|
||||
material = self.material
|
||||
value_in_kg_per_m3 = value * 1e9
|
||||
material['Density'] = unicode(value_in_kg_per_m3) + " kg/m^3" # SvdW:Keep density in SI units for easier readability
|
||||
self.material = material
|
||||
|
||||
def pr_changed(self, value):
|
||||
old_pr = Units.Quantity(self.material['PoissonRatio'])
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_pr) / value < 1 + variation):
|
||||
# PoissonRatio has changed
|
||||
material = self.material
|
||||
material['PoissonRatio'] = unicode(value)
|
||||
self.material = material
|
||||
|
||||
def tc_changed(self, value):
|
||||
old_tc = Units.Quantity(self.material['ThermalConductivity']).getValueAs("W/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_tc) / value < 1 + variation):
|
||||
# ThermalConductivity has changed
|
||||
material = self.material
|
||||
value_in_W_per_mK = value * 1e-3 # To compensate for use of SI units
|
||||
material['ThermalConductivity'] = unicode(value_in_W_per_mK) + " W/m/K"
|
||||
self.material = material
|
||||
|
||||
def tec_changed(self, value):
|
||||
old_tec = Units.Quantity(self.material['ThermalExpansionCoefficient']).getValueAs("um/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_tec) / value < 1 + variation):
|
||||
# ThermalExpansionCoefficient has changed
|
||||
material = self.material
|
||||
value_in_um_per_mK = value * 1e6 # To compensate for use of SI units
|
||||
material['ThermalExpansionCoefficient'] = unicode(value_in_um_per_mK) + " um/m/K"
|
||||
self.material = material
|
||||
|
||||
def sh_changed(self, value):
|
||||
old_sh = Units.Quantity(self.material['SpecificHeat']).getValueAs("J/kg/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_sh) / value < 1 + variation):
|
||||
# SpecificHeat has changed
|
||||
material = self.material
|
||||
value_in_J_per_kgK = value * 1e-6 # To compensate for use of SI units
|
||||
material['SpecificHeat'] = unicode(value_in_J_per_kgK) + " J/kg/K"
|
||||
self.material = material
|
||||
|
||||
################ fluidic #########################
|
||||
def vtec_changed(self, value):
|
||||
old_vtec = Units.Quantity(self.material['VolumetricThermalExpansionCoefficient']).getValueAs("m/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_vtec) / value < 1 + variation):
|
||||
# VolumetricThermalExpansionCoefficient has changed
|
||||
material = self.material
|
||||
value_in_one_per_K = value
|
||||
material['VolumetricThermalExpansionCoefficient'] = unicode(value_in_one_per_K) + " m/m/K"
|
||||
self.material = material
|
||||
|
||||
def kinematic_viscosity_changed(self, value):
|
||||
old_nu = Units.Quantity(self.material['KinematicViscosity']).getValueAs("m^2/s")
|
||||
variation = 0.000001
|
||||
if value:
|
||||
if not (1 - variation < float(old_nu) / value < 1 + variation):
|
||||
# KinematicViscosity has changed
|
||||
material = self.material
|
||||
value_in_m2_per_second = value
|
||||
material['KinematicViscosity'] = unicode(value_in_m2_per_second) + " m^2/s"
|
||||
self.material = material
|
||||
|
||||
def choose_material(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
mat_file_path = self.form.cb_materials.itemData(index)
|
||||
self.material = self.materials[mat_file_path]
|
||||
self.form.cb_materials.setCurrentIndex(index)
|
||||
self.check_material_keys()
|
||||
self.set_mat_params_in_combo_box(self.material)
|
||||
gen_mat_desc = ""
|
||||
if 'Description' in self.material:
|
||||
gen_mat_desc = self.material['Description']
|
||||
self.form.l_mat_description.setText(gen_mat_desc)
|
||||
|
||||
def get_material_name(self, material):
|
||||
if 'Name' in self.material:
|
||||
return self.material['Name']
|
||||
else:
|
||||
return 'None'
|
||||
|
||||
def get_material_path(self, material):
|
||||
for a_mat in self.materials:
|
||||
unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items())
|
||||
if len(unmatched_items) == 0:
|
||||
return a_mat
|
||||
return ""
|
||||
|
||||
def set_mat_params_in_combo_box(self, matmap):
|
||||
if 'YoungsModulus' in matmap:
|
||||
ym_new_unit = "MPa"
|
||||
ym = FreeCAD.Units.Quantity(matmap['YoungsModulus'])
|
||||
ym_with_new_unit = ym.getValueAs(ym_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(ym_with_new_unit, ym_new_unit))
|
||||
self.form.input_fd_young_modulus.setText(q.UserString)
|
||||
if 'PoissonRatio' in matmap:
|
||||
self.form.spinBox_poisson_ratio.setValue(float(matmap['PoissonRatio']))
|
||||
# Fluidic properties
|
||||
if 'KinematicViscosity' in matmap:
|
||||
nu_new_unit = "m^2/s"
|
||||
nu = FreeCAD.Units.Quantity(matmap['KinematicViscosity'])
|
||||
nu_with_new_unit = nu.getValueAs(nu_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(nu_with_new_unit, nu_new_unit))
|
||||
self.form.input_fd_kinematic_viscosity.setText(q.UserString)
|
||||
# For isotropic materials the volumetric thermal expansion coefficient is three times the linear coefficient:
|
||||
if 'VolumetricThermalExpansionCoefficient' in matmap: # linear, only for solid
|
||||
vtec_new_unit = "m/m/K"
|
||||
vtec = FreeCAD.Units.Quantity(matmap['VolumetricThermalExpansionCoefficient'])
|
||||
vtec_with_new_unit = vtec.getValueAs(vtec_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(vtec_with_new_unit, vtec_new_unit))
|
||||
self.form.input_fd_vol_expansion_coefficient.setText(q.UserString)
|
||||
if 'Density' in matmap:
|
||||
density_new_unit = "kg/m^3"
|
||||
density = FreeCAD.Units.Quantity(matmap['Density'])
|
||||
density_with_new_unit = density.getValueAs(density_new_unit)
|
||||
#self.form.input_fd_density.setText("{} {}".format(density_with_new_unit, density_new_unit))
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(density_with_new_unit, density_new_unit))
|
||||
self.form.input_fd_density.setText(q.UserString)
|
||||
# thermal properties
|
||||
if 'ThermalConductivity' in matmap:
|
||||
tc_new_unit = "W/m/K"
|
||||
tc = FreeCAD.Units.Quantity(matmap['ThermalConductivity'])
|
||||
tc_with_new_unit = tc.getValueAs(tc_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(tc_with_new_unit, tc_new_unit))
|
||||
self.form.input_fd_thermal_conductivity.setText(q.UserString)
|
||||
if 'ThermalExpansionCoefficient' in matmap: # linear, only for solid
|
||||
tec_new_unit = "um/m/K"
|
||||
tec = FreeCAD.Units.Quantity(matmap['ThermalExpansionCoefficient'])
|
||||
tec_with_new_unit = tec.getValueAs(tec_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(tec_with_new_unit, tec_new_unit))
|
||||
self.form.input_fd_expansion_coefficient.setText(q.UserString)
|
||||
if 'SpecificHeat' in matmap:
|
||||
sh_new_unit = "J/kg/K"
|
||||
sh = FreeCAD.Units.Quantity(matmap['SpecificHeat'])
|
||||
sh_with_new_unit = sh.getValueAs(sh_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(sh_with_new_unit, sh_new_unit))
|
||||
self.form.input_fd_specific_heat.setText(q.UserString)
|
||||
|
||||
def add_transient_material(self, material):
|
||||
material_name = self.get_material_name(material)
|
||||
self.form.cb_materials.addItem(QtGui.QIcon(":/icons/help-browser.svg"), material_name, material_name)
|
||||
self.materials[material_name] = material
|
||||
|
||||
######################## material import and export ###################
|
||||
def import_materials(self):
|
||||
self.materials = {}
|
||||
self.pathList = []
|
||||
self.form.cb_materials.clear()
|
||||
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
if self.obj.Category == 'Fluid':
|
||||
self.import_fluid_materials()
|
||||
else:
|
||||
self.import_solid_materials()
|
||||
|
||||
def import_solid_materials(self):
|
||||
use_built_in_materials = self.fem_prefs.GetBool("UseBuiltInMaterials", True)
|
||||
if use_built_in_materials:
|
||||
system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/StandardMaterial"
|
||||
self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg")
|
||||
|
||||
use_mat_from_config_dir = self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True)
|
||||
if use_mat_from_config_dir:
|
||||
user_mat_dirname = FreeCAD.getUserAppDataDir() + "Materials"
|
||||
self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg")
|
||||
|
||||
use_mat_from_custom_dir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
if use_mat_from_custom_dir:
|
||||
custom_mat_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
|
||||
|
||||
def import_fluid_materials(self):
|
||||
#use_built_in_materials = self.fem_prefs.GetBool("UseBuiltInMaterials", True)
|
||||
#if use_built_in_materials:
|
||||
system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/FluidMaterial"
|
||||
self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg")
|
||||
|
||||
use_mat_from_config_dir = self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True)
|
||||
if use_mat_from_config_dir:
|
||||
user_mat_dirname = FreeCAD.getUserAppDataDir() + "FluidMaterial"
|
||||
self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg")
|
||||
|
||||
use_mat_from_custom_dir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
if use_mat_from_custom_dir:
|
||||
custom_mat_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
|
||||
|
||||
def add_mat_dir(self, mat_dir, icon):
|
||||
import glob
|
||||
import os
|
||||
import Material
|
||||
mat_file_extension = ".FCMat"
|
||||
ext_len = len(mat_file_extension)
|
||||
dir_path_list = glob.glob(mat_dir + '/*' + mat_file_extension)
|
||||
self.pathList = self.pathList + dir_path_list
|
||||
material_name_list = []
|
||||
for a_path in dir_path_list:
|
||||
material_name = os.path.basename(a_path[:-ext_len])
|
||||
self.materials[a_path] = Material.importFCMat(a_path)
|
||||
material_name_list.append([material_name, a_path])
|
||||
material_name_list.sort()
|
||||
for mat in material_name_list:
|
||||
self.form.cb_materials.addItem(QtGui.QIcon(icon), mat[0], mat[1])
|
||||
|
||||
def export_FCMat(self, fileName, matDict):
|
||||
"""
|
||||
Write a material dictionary to a FCMat file, a version without group support, with Python3
|
||||
<https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Material/Material.py>
|
||||
"""
|
||||
try:
|
||||
import ConfigParser as configparser
|
||||
except:
|
||||
import configparser # Python 3
|
||||
# himport string
|
||||
Config = configparser.ConfigParser()
|
||||
Config.optionxform = str # disable conversion all uppercase leter in key into lower case
|
||||
|
||||
# ignore creating group, just fill all into group 'FCMat'
|
||||
grp = 'FCMat'
|
||||
if not Config.has_section(grp):
|
||||
Config.add_section(grp)
|
||||
for x in matDict.keys():
|
||||
Config.set(grp, x, matDict[x])
|
||||
|
||||
Preamble = "# This is a FreeCAD material-card file\n\n"
|
||||
# Writing our configuration file to 'example.cfg'
|
||||
with open(fileName, 'wb') as configfile:
|
||||
configfile.write(Preamble)
|
||||
Config.write(configfile)
|
||||
|
||||
def export_material(self):
|
||||
import os
|
||||
if self.obj.Category == 'Fluid':
|
||||
MaterialDir = 'FluidMaterial'
|
||||
else:
|
||||
MaterialDir = 'Material'
|
||||
_UseMaterialsFromCustomDir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
if _UseMaterialsFromCustomDir and _dir != "" and os.path.isdir(_dir):
|
||||
TargetDir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
elif self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True):
|
||||
TargetDir = FreeCAD.getUserAppDataDir() + os.path.sep + MaterialDir # $HOME/.FreeCAD
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("Customed material saving directory is not setup in Fem preference")
|
||||
if not os.path.exists(TargetDir):
|
||||
os.mkdir(TargetDir)
|
||||
|
||||
saveName, Filter = QFileDialog.getSaveFileName(None, "Save a Material property file", TargetDir, "*.FCMat")
|
||||
if not saveName == "":
|
||||
print(saveName)
|
||||
knownMaterials = [self.form.cb_materials.itemText(i) for i in range(self.form.cb_materials.count())]
|
||||
material_name = os.path.basename(saveName[:-len('.FCMat')])
|
||||
if material_name not in knownMaterials:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully save the Material property file: " + saveName + "\n")
|
||||
else:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully overwritren the Material property file: " + saveName + "\n")
|
||||
"""
|
||||
msgBox = QMessageBox()
|
||||
msgBox.setText("FcMat file name {} has existed in {} or system folder, overwriting?\n".format(saveName, TargetDir))
|
||||
msgBox.addButton(QMessageBox.Yes)
|
||||
msgBox.addButton(QMessageBox.No)
|
||||
msgBox.setDefaultButton(QMessageBox.No)
|
||||
ret = msgBox.exec_()
|
||||
if ret == QMessageBox.Yes:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully overwritren the Material property file: "+ saveName + "\n")
|
||||
"""
|
||||
|
||||
###################geometry reference selection #################
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
if ref[1]:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
else:
|
||||
refname_to_compare_listentry = ref[0].Name
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' --> ', selection[0].Name, ' --> ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
if ref[1]:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
else:
|
||||
item_name = ref[0].Name
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,204 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshBoundaryLayer"
|
||||
__author__ = "Bernd Hahnebach, Qingfeng Xia"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshBoundaryLayer
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _TaskPanelFemMeshBoundaryLayer:
|
||||
'''The TaskPanel for editing References property of FemMeshBoundaryLayer objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces for 3D, Edges for 2D by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui")
|
||||
|
||||
QtCore.QObject.connect(self.form.bl_number_of_layers, QtCore.SIGNAL("valueChanged(int)"), self.bl_number_of_layers_changed)
|
||||
QtCore.QObject.connect(self.form.bl_min_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.bl_min_thickness_changed)
|
||||
QtCore.QObject.connect(self.form.bl_growth_rate, QtCore.SIGNAL("valueChanged(double)"), self.bl_growth_rate_changed) # becareful of signal signature for QDoubleSpinbox
|
||||
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_mesh_boundarylayer_props()
|
||||
self.update()
|
||||
|
||||
def get_mesh_boundarylayer_props(self):
|
||||
self.bl_min_thickness = self.obj.MinimumThickness
|
||||
self.bl_number_of_layers = self.obj.NumberOfLayers
|
||||
self.bl_growth_rate = self.obj.GrowthRate
|
||||
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_mesh_boundarylayer_props(self):
|
||||
self.obj.MinimumThickness = self.bl_min_thickness
|
||||
self.obj.NumberOfLayers = self.bl_number_of_layers
|
||||
self.obj.GrowthRate = self.bl_growth_rate
|
||||
self.obj.References = self.references
|
||||
|
||||
def update(self):
|
||||
'fills the widgets with data'
|
||||
self.form.bl_min_thickness.setText(self.bl_min_thickness.UserString)
|
||||
self.form.bl_number_of_layers.setValue(self.bl_number_of_layers)
|
||||
self.form.bl_growth_rate.setValue(self.bl_growth_rate)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def bl_min_thickness_changed(self, base_quantity_value):
|
||||
self.bl_min_thickness = base_quantity_value
|
||||
|
||||
def bl_number_of_layers_changed(self, value):
|
||||
self.bl_number_of_layers = value
|
||||
|
||||
def bl_growth_rate_changed(self, value):
|
||||
self.bl_growth_rate = value
|
||||
|
||||
def accept(self):
|
||||
self.set_mesh_boundarylayer_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
############### identical to FemMeshRegion ############
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
@@ -1,174 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshGmsh"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshGmsh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import time
|
||||
import PyObjects._FemMeshGmsh
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGmsh:
|
||||
'''The TaskPanel for editing References property of FemMeshGmsh objects and creation of new FEM mesh'''
|
||||
def __init__(self, obj):
|
||||
self.mesh_obj = obj
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshGmsh.ui")
|
||||
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(100) # 100 milli seconds
|
||||
self.gmsh_runs = False
|
||||
self.console_message_gmsh = ''
|
||||
|
||||
QtCore.QObject.connect(self.form.if_max, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.max_changed)
|
||||
QtCore.QObject.connect(self.form.if_min, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.min_changed)
|
||||
QtCore.QObject.connect(self.form.cb_dimension, QtCore.SIGNAL("activated(int)"), self.choose_dimension)
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.update_timer_text)
|
||||
|
||||
self.form.cb_dimension.addItems(PyObjects._FemMeshGmsh._FemMeshGmsh.known_element_dimensions)
|
||||
|
||||
self.get_mesh_params()
|
||||
self.get_active_analysis()
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
|
||||
# show a OK, a apply and a Cancel button
|
||||
# def reject() is called on Cancel button
|
||||
# def clicked(self, button) is needed, to access the apply button
|
||||
|
||||
def accept(self):
|
||||
self.set_mesh_params()
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def clicked(self, button):
|
||||
if button == QtGui.QDialogButtonBox.Apply:
|
||||
self.set_mesh_params()
|
||||
self.run_gmsh()
|
||||
|
||||
def get_mesh_params(self):
|
||||
self.clmax = self.mesh_obj.CharacteristicLengthMax
|
||||
self.clmin = self.mesh_obj.CharacteristicLengthMin
|
||||
self.dimension = self.mesh_obj.ElementDimension
|
||||
|
||||
def set_mesh_params(self):
|
||||
self.mesh_obj.CharacteristicLengthMax = self.clmax
|
||||
self.mesh_obj.CharacteristicLengthMin = self.clmin
|
||||
self.mesh_obj.ElementDimension = self.dimension
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_max.setText(self.clmax.UserString)
|
||||
self.form.if_min.setText(self.clmin.UserString)
|
||||
index_dimension = self.form.cb_dimension.findText(self.dimension)
|
||||
self.form.cb_dimension.setCurrentIndex(index_dimension)
|
||||
|
||||
def console_log(self, message="", color="#000000"):
|
||||
self.console_message_gmsh = self.console_message_gmsh + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.te_output.setText(self.console_message_gmsh)
|
||||
self.form.te_output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def update_timer_text(self):
|
||||
# print('timer1')
|
||||
if self.gmsh_runs:
|
||||
print('timer2')
|
||||
# print('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def max_changed(self, base_quantity_value):
|
||||
self.clmax = base_quantity_value
|
||||
|
||||
def min_changed(self, base_quantity_value):
|
||||
self.clmin = base_quantity_value
|
||||
|
||||
def choose_dimension(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_dimension.setCurrentIndex(index)
|
||||
self.dimension = str(self.form.cb_dimension.itemText(index)) # form returns unicode
|
||||
|
||||
def run_gmsh(self):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
part = self.obj.Part
|
||||
if self.mesh_obj.MeshRegionList:
|
||||
if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): # other part obj might not have a Proxy, thus an exception would be raised
|
||||
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."
|
||||
QtGui.QMessageBox.critical(None, "Shape to mesh is a BooleanFragmentsCompound and mesh regions are defined", error_message)
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.console_message_gmsh = ''
|
||||
self.gmsh_runs = True
|
||||
self.console_log("We are going to start ...")
|
||||
self.get_active_analysis()
|
||||
import femmesh.gmshtools as gmshtools
|
||||
gmsh_mesh = gmshtools.GmshTools(self.obj, self.analysis)
|
||||
self.console_log("Start Gmsh ...")
|
||||
error = ''
|
||||
try:
|
||||
error = gmsh_mesh.create_mesh()
|
||||
except:
|
||||
import sys
|
||||
print("Unexpected error when creating mesh: ", sys.exc_info()[0])
|
||||
if error:
|
||||
print(error)
|
||||
self.console_log('Gmsh had warnings ...')
|
||||
self.console_log(error, '#FF0000')
|
||||
else:
|
||||
self.console_log('Clean run of Gmsh')
|
||||
self.console_log("Gmsh done!")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.Timer.stop()
|
||||
self.update()
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def get_active_analysis(self):
|
||||
import FemGui
|
||||
self.analysis = FemGui.getActiveAnalysis()
|
||||
if self.analysis:
|
||||
for m in FemGui.getActiveAnalysis().Group:
|
||||
if m.Name == self.mesh_obj.Name:
|
||||
print('Active analysis found: ' + self.analysis.Name)
|
||||
return
|
||||
else:
|
||||
# print('Mesh is not member of active analysis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
else:
|
||||
# print('No active analyis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
@@ -1,224 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshGroup"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshGroup
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGroup:
|
||||
'''The TaskPanel for editing References property of FemMeshGroup objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshGroup.ui")
|
||||
QtCore.QObject.connect(self.form.rb_name, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_name)
|
||||
QtCore.QObject.connect(self.form.rb_label, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_label)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_meshgroup_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_meshgroup_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_meshgroup_props(self):
|
||||
self.use_label = self.obj.UseLabel
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_meshgroup_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.UseLabel = self.use_label
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.rb_name.setChecked(not self.use_label)
|
||||
self.form.rb_label.setChecked(self.use_label)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def choose_exportidentifier_name(self, state):
|
||||
self.use_label = not state
|
||||
|
||||
def choose_exportidentifier_label(self, state):
|
||||
self.use_label = state
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,219 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2016 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "_TaskPanelFemMeshRegion"
|
||||
__author__ = "Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemMeshRegion
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
from PySide import QtCore
|
||||
|
||||
|
||||
class _TaskPanelFemMeshRegion:
|
||||
'''The TaskPanel for editing References property of FemMeshRegion objects'''
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshRegion.ui")
|
||||
QtCore.QObject.connect(self.form.if_elelen, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.elelen_changed)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_meshregion_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_meshregion_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_meshregion_props(self):
|
||||
self.elelen = self.obj.CharacteristicLength
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_meshregion_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.CharacteristicLength = self.elelen
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_elelen.setText(self.elelen.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def elelen_changed(self, base_quantity_value):
|
||||
self.elelen = base_quantity_value
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
@@ -1,421 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2013-2015 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "Result Control Task Panel"
|
||||
__author__ = "Juergen Riegel, Michael Hindley"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemResultShow
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCAD
|
||||
import numpy as np
|
||||
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
import femresult.resulttools as resulttools
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
class _TaskPanelFemResultShow:
|
||||
'''The task panel for the post-processing'''
|
||||
def __init__(self, obj):
|
||||
self.result_obj = obj
|
||||
self.mesh_obj = self.result_obj.Mesh
|
||||
# task panel should be started by use of setEdit of view provider
|
||||
# in view provider checks: Mesh, active analysis and if Mesh and result are in active analysis
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemResultShow.ui")
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
self.restore_result_settings_in_dialog = self.fem_prefs.GetBool("RestoreResultDialog", True)
|
||||
|
||||
# Connect Signals and Slots
|
||||
# result type radio buttons
|
||||
QtCore.QObject.connect(self.form.rb_none, QtCore.SIGNAL("toggled(bool)"), self.none_selected)
|
||||
QtCore.QObject.connect(self.form.rb_abs_displacement, QtCore.SIGNAL("toggled(bool)"), self.abs_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_x_displacement, QtCore.SIGNAL("toggled(bool)"), self.x_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_y_displacement, QtCore.SIGNAL("toggled(bool)"), self.y_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_z_displacement, QtCore.SIGNAL("toggled(bool)"), self.z_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_temperature, QtCore.SIGNAL("toggled(bool)"), self.temperature_selected)
|
||||
QtCore.QObject.connect(self.form.rb_vm_stress, QtCore.SIGNAL("toggled(bool)"), self.vm_stress_selected)
|
||||
QtCore.QObject.connect(self.form.rb_maxprin, QtCore.SIGNAL("toggled(bool)"), self.max_prin_selected)
|
||||
QtCore.QObject.connect(self.form.rb_minprin, QtCore.SIGNAL("toggled(bool)"), self.min_prin_selected)
|
||||
QtCore.QObject.connect(self.form.rb_max_shear_stress, QtCore.SIGNAL("toggled(bool)"), self.max_shear_selected)
|
||||
QtCore.QObject.connect(self.form.rb_massflowrate, QtCore.SIGNAL("toggled(bool)"), self.massflowrate_selected)
|
||||
QtCore.QObject.connect(self.form.rb_networkpressure, QtCore.SIGNAL("toggled(bool)"), self.networkpressure_selected)
|
||||
QtCore.QObject.connect(self.form.rb_peeq, QtCore.SIGNAL("toggled(bool)"), self.peeq_selected)
|
||||
|
||||
# displacement
|
||||
QtCore.QObject.connect(self.form.cb_show_displacement, QtCore.SIGNAL("clicked(bool)"), self.show_displacement)
|
||||
QtCore.QObject.connect(self.form.hsb_displacement_factor, QtCore.SIGNAL("valueChanged(int)"), self.hsb_disp_factor_changed)
|
||||
QtCore.QObject.connect(self.form.sb_displacement_factor, QtCore.SIGNAL("valueChanged(int)"), self.sb_disp_factor_changed)
|
||||
QtCore.QObject.connect(self.form.sb_displacement_factor_max, QtCore.SIGNAL("valueChanged(int)"), self.sb_disp_factor_max_changed)
|
||||
|
||||
# user defined equation
|
||||
QtCore.QObject.connect(self.form.user_def_eq, QtCore.SIGNAL("textchanged()"), self.user_defined_text)
|
||||
QtCore.QObject.connect(self.form.calculate, QtCore.SIGNAL("clicked()"), self.calculate)
|
||||
|
||||
self.update()
|
||||
if self.restore_result_settings_in_dialog:
|
||||
self.restore_result_dialog()
|
||||
else:
|
||||
self.restore_initial_result_dialog()
|
||||
|
||||
def restore_result_dialog(self):
|
||||
try:
|
||||
rt = FreeCAD.FEM_dialog["results_type"]
|
||||
if rt == "None":
|
||||
self.form.rb_none.setChecked(True)
|
||||
self.none_selected(True)
|
||||
elif rt == "Uabs":
|
||||
self.form.rb_abs_displacement.setChecked(True)
|
||||
self.abs_displacement_selected(True)
|
||||
elif rt == "U1":
|
||||
self.form.rb_x_displacement.setChecked(True)
|
||||
self.x_displacement_selected(True)
|
||||
elif rt == "U2":
|
||||
self.form.rb_y_displacement.setChecked(True)
|
||||
self.y_displacement_selected(True)
|
||||
elif rt == "U3":
|
||||
self.form.rb_z_displacement.setChecked(True)
|
||||
self.z_displacement_selected(True)
|
||||
elif rt == "Temp":
|
||||
self.form.rb_temperature.setChecked(True)
|
||||
self.temperature_selected(True)
|
||||
elif rt == "Sabs":
|
||||
self.form.rb_vm_stress.setChecked(True)
|
||||
self.vm_stress_selected(True)
|
||||
elif rt == "MaxPrin":
|
||||
self.form.rb_maxprin.setChecked(True)
|
||||
self.max_prin_selected(True)
|
||||
elif rt == "MinPrin":
|
||||
self.form.rb_minprin.setChecked(True)
|
||||
self.min_prin_selected(True)
|
||||
elif rt == "MaxShear":
|
||||
self.form.rb_max_shear_stress.setChecked(True)
|
||||
self.max_shear_selected(True)
|
||||
elif rt == "MFlow":
|
||||
self.form.rb_massflowrate.setChecked(True)
|
||||
self.massflowrate_selected(True)
|
||||
elif rt == "NPress":
|
||||
self.form.rb_networkpressure.setChecked(True)
|
||||
self.networkpressure_selected(True)
|
||||
elif rt == "Peeq":
|
||||
self.form.rb_peeq.setChecked(True)
|
||||
self.peeq_selected(True)
|
||||
|
||||
sd = FreeCAD.FEM_dialog["show_disp"]
|
||||
self.form.cb_show_displacement.setChecked(sd)
|
||||
self.show_displacement(sd)
|
||||
|
||||
df = FreeCAD.FEM_dialog["disp_factor"]
|
||||
dfm = FreeCAD.FEM_dialog["disp_factor_max"]
|
||||
self.form.hsb_displacement_factor.setMaximum(dfm)
|
||||
self.form.hsb_displacement_factor.setValue(df)
|
||||
self.form.sb_displacement_factor_max.setValue(dfm)
|
||||
self.form.sb_displacement_factor.setValue(df)
|
||||
except:
|
||||
self.restore_initial_result_dialog()
|
||||
|
||||
def restore_initial_result_dialog(self):
|
||||
FreeCAD.FEM_dialog = {"results_type": "None", "show_disp": False,
|
||||
"disp_factor": 0, "disp_factor_max": 100}
|
||||
self.reset_mesh_deformation()
|
||||
self.reset_mesh_color()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def get_result_stats(self, type_name):
|
||||
return resulttools.get_stats(self.result_obj, type_name)
|
||||
|
||||
def none_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "None"
|
||||
self.set_result_stats("mm", 0.0, 0.0, 0.0)
|
||||
self.reset_mesh_color()
|
||||
|
||||
def abs_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Uabs"
|
||||
self.select_displacement_type("Uabs")
|
||||
|
||||
def x_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U1"
|
||||
self.select_displacement_type("U1")
|
||||
|
||||
def y_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U2"
|
||||
self.select_displacement_type("U2")
|
||||
|
||||
def z_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U3"
|
||||
self.select_displacement_type("U3")
|
||||
|
||||
def vm_stress_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Sabs"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.StressValues)
|
||||
(minm, avg, maxm) = self.get_result_stats("Sabs")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def max_shear_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MaxShear"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.MaxShear)
|
||||
(minm, avg, maxm) = self.get_result_stats("MaxShear")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def max_prin_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MaxPrin"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.PrincipalMax)
|
||||
(minm, avg, maxm) = self.get_result_stats("MaxPrin")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def temperature_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Temp"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.Temperature)
|
||||
(minm, avg, maxm) = self.get_result_stats("Temp")
|
||||
self.set_result_stats("K", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def massflowrate_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MFlow"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.MassFlowRate)
|
||||
(minm, avg, maxm) = self.get_result_stats("MFlow")
|
||||
self.set_result_stats("kg/s", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def networkpressure_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "NPress"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.NetworkPressure)
|
||||
(minm, avg, maxm) = self.get_result_stats("NPress")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def min_prin_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MinPrin"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.PrincipalMin)
|
||||
(minm, avg, maxm) = self.get_result_stats("MinPrin")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def peeq_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Peeq"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.Peeq)
|
||||
(minm, avg, maxm) = self.get_result_stats("Peeq")
|
||||
self.set_result_stats("", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def user_defined_text(self, equation):
|
||||
FreeCAD.FEM_dialog["results_type"] = "user"
|
||||
self.form.user_def_eq.toPlainText()
|
||||
|
||||
def calculate(self):
|
||||
FreeCAD.FEM_dialog["results_type"] = "None"
|
||||
self.update()
|
||||
self.restore_result_dialog()
|
||||
# Convert existing values to numpy array
|
||||
P1 = np.array(self.result_obj.PrincipalMax)
|
||||
P2 = np.array(self.result_obj.PrincipalMed)
|
||||
P3 = np.array(self.result_obj.PrincipalMin)
|
||||
Von = np.array(self.result_obj.StressValues)
|
||||
Peeq = np.array(self.result_obj.Peeq)
|
||||
T = np.array(self.result_obj.Temperature)
|
||||
MF = np.array(self.result_obj.MassFlowRate)
|
||||
NP = np.array(self.result_obj.NetworkPressure)
|
||||
dispvectors = np.array(self.result_obj.DisplacementVectors)
|
||||
x = np.array(dispvectors[:, 0])
|
||||
y = np.array(dispvectors[:, 1])
|
||||
z = np.array(dispvectors[:, 2])
|
||||
stressvectors = np.array(self.result_obj.StressVectors)
|
||||
sx = np.array(stressvectors[:, 0])
|
||||
sy = np.array(stressvectors[:, 1])
|
||||
sz = np.array(stressvectors[:, 2])
|
||||
strainvectors = np.array(self.result_obj.StrainVectors)
|
||||
ex = np.array(strainvectors[:, 0])
|
||||
ey = np.array(strainvectors[:, 1])
|
||||
ez = np.array(strainvectors[:, 2])
|
||||
userdefined_eq = self.form.user_def_eq.toPlainText() # Get equation to be used
|
||||
UserDefinedFormula = eval(userdefined_eq).tolist()
|
||||
self.result_obj.UserDefined = UserDefinedFormula
|
||||
minm = min(UserDefinedFormula)
|
||||
avg = sum(UserDefinedFormula) / len(UserDefinedFormula)
|
||||
maxm = max(UserDefinedFormula)
|
||||
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, UserDefinedFormula)
|
||||
self.set_result_stats("", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
del x, y, z, T, Von, Peeq, P1, P2, P3, sx, sy, sz, ex, ey, ez, MF, NP # Dummy use to get around flake8, varibles not being used
|
||||
|
||||
def select_displacement_type(self, disp_type):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if disp_type == "Uabs":
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.DisplacementLengths)
|
||||
else:
|
||||
match = {"U1": 0, "U2": 1, "U3": 2}
|
||||
d = zip(*self.result_obj.DisplacementVectors)
|
||||
displacements = list(d[match[disp_type]])
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, displacements)
|
||||
(minm, avg, maxm) = self.get_result_stats(disp_type)
|
||||
self.set_result_stats("mm", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def set_result_stats(self, unit, minm, avg, maxm):
|
||||
self.form.le_min.setProperty("unit", unit)
|
||||
self.form.le_min.setText("{:.6} {}".format(minm, unit))
|
||||
self.form.le_avg.setProperty("unit", unit)
|
||||
self.form.le_avg.setText("{:.6} {}".format(avg, unit))
|
||||
self.form.le_max.setProperty("unit", unit)
|
||||
self.form.le_max.setText("{:.6} {}".format(maxm, unit))
|
||||
|
||||
def update_displacement(self, factor=None):
|
||||
if factor is None:
|
||||
if FreeCAD.FEM_dialog["show_disp"]:
|
||||
factor = self.form.hsb_displacement_factor.value()
|
||||
else:
|
||||
factor = 0.0
|
||||
self.mesh_obj.ViewObject.applyDisplacement(factor)
|
||||
|
||||
def show_displacement(self, checked):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
FreeCAD.FEM_dialog["show_disp"] = checked
|
||||
if "result_obj" in FreeCAD.FEM_dialog:
|
||||
if FreeCAD.FEM_dialog["result_obj"] != self.result_obj:
|
||||
self.update_displacement()
|
||||
FreeCAD.FEM_dialog["result_obj"] = self.result_obj
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeDisplacementByVectors(self.result_obj.NodeNumbers, self.result_obj.DisplacementVectors)
|
||||
self.update_displacement()
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def hsb_disp_factor_changed(self, value):
|
||||
self.form.sb_displacement_factor.setValue(value)
|
||||
self.update_displacement()
|
||||
|
||||
def sb_disp_factor_max_changed(self, value):
|
||||
FreeCAD.FEM_dialog["disp_factor_max"] = value
|
||||
self.form.hsb_displacement_factor.setMaximum(value)
|
||||
|
||||
def sb_disp_factor_changed(self, value):
|
||||
FreeCAD.FEM_dialog["disp_factor"] = value
|
||||
self.form.hsb_displacement_factor.setValue(value)
|
||||
|
||||
def disable_empty_result_buttons(self):
|
||||
''' disable radio buttons if result does not exists in result object'''
|
||||
'''assignments
|
||||
DisplacementLengths --> rb_abs_displacement
|
||||
DisplacementVectors --> rb_x_displacement, rb_y_displacement, rb_z_displacement
|
||||
Temperature --> rb_temperature
|
||||
StressValues --> rb_vm_stress
|
||||
PrincipalMax --> rb_maxprin
|
||||
PrincipalMin --> rb_minprin
|
||||
MaxShear --> rb_max_shear_stress
|
||||
MassFlowRate --> rb_massflowrate
|
||||
NetworkPressure --> rb_networkpressure
|
||||
Peeq --> rb_peeq'''
|
||||
if len(self.result_obj.DisplacementLengths) == 0:
|
||||
self.form.rb_abs_displacement.setEnabled(0)
|
||||
if len(self.result_obj.DisplacementVectors) == 0:
|
||||
self.form.rb_x_displacement.setEnabled(0)
|
||||
self.form.rb_y_displacement.setEnabled(0)
|
||||
self.form.rb_z_displacement.setEnabled(0)
|
||||
if len(self.result_obj.Temperature) == 0:
|
||||
self.form.rb_temperature.setEnabled(0)
|
||||
if len(self.result_obj.StressValues) == 0:
|
||||
self.form.rb_vm_stress.setEnabled(0)
|
||||
if len(self.result_obj.PrincipalMax) == 0:
|
||||
self.form.rb_maxprin.setEnabled(0)
|
||||
if len(self.result_obj.PrincipalMin) == 0:
|
||||
self.form.rb_minprin.setEnabled(0)
|
||||
if len(self.result_obj.MaxShear) == 0:
|
||||
self.form.rb_max_shear_stress.setEnabled(0)
|
||||
if len(self.result_obj.MassFlowRate) == 0:
|
||||
self.form.rb_massflowrate.setEnabled(0)
|
||||
if len(self.result_obj.NetworkPressure) == 0:
|
||||
self.form.rb_networkpressure.setEnabled(0)
|
||||
if len(self.result_obj.Peeq) == 0:
|
||||
self.form.rb_peeq.setEnabled(0)
|
||||
|
||||
def update(self):
|
||||
self.suitable_results = False
|
||||
self.disable_empty_result_buttons()
|
||||
if (self.mesh_obj.FemMesh.NodeCount == len(self.result_obj.NodeNumbers)):
|
||||
self.suitable_results = True
|
||||
hide_parts_constraints()
|
||||
else:
|
||||
if not self.mesh_obj.FemMesh.VolumeCount:
|
||||
error_message = 'FEM: Graphical bending stress output for beam or shell FEM Meshes not yet supported.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
else:
|
||||
error_message = 'FEM: Result node numbers are not equal to FEM Mesh NodeCount.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
|
||||
def reset_mesh_deformation(self):
|
||||
self.mesh_obj.ViewObject.applyDisplacement(0.0)
|
||||
|
||||
def reset_mesh_color(self):
|
||||
self.mesh_obj.ViewObject.NodeColor = {}
|
||||
self.mesh_obj.ViewObject.ElementColor = {}
|
||||
node_numbers = self.mesh_obj.FemMesh.Nodes.keys()
|
||||
zero_values = [0] * len(node_numbers)
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(node_numbers, zero_values)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.Control.closeDialog() # if the taks panell is called from Command obj is not in edit mode thus reset edit does not cleses the dialog, may be do not call but set in edit instead
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
|
||||
# helper
|
||||
def hide_parts_constraints():
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
hide_constraints = fem_prefs.GetBool("HideConstraint", False)
|
||||
if hide_constraints:
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if o.isDerivedFrom('Fem::FemAnalysis'):
|
||||
for acnstrmesh in FemGui.getActiveAnalysis().Group:
|
||||
if "Constraint" in acnstrmesh.TypeId:
|
||||
acnstrmesh.ViewObject.Visibility = False
|
||||
break
|
||||
@@ -1,293 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2013-2015 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
__title__ = "CalculiX Job Control Task Panel"
|
||||
__author__ = "Juergen Riegel"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package TaskPanelFemSolverCalculix
|
||||
# \ingroup FEM
|
||||
|
||||
import FemToolsCcx
|
||||
import FreeCAD
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import FreeCADGui
|
||||
import FemGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
unicode = str
|
||||
|
||||
|
||||
class _TaskPanelFemSolverCalculix:
|
||||
def __init__(self, solver_object):
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemSolverCalculix.ui")
|
||||
self.ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
|
||||
ccx_binary = self.ccx_prefs.GetString("ccxBinaryPath", "")
|
||||
if ccx_binary:
|
||||
self.CalculixBinary = ccx_binary
|
||||
print ("Using CalculiX binary path from FEM preferences: {}".format(ccx_binary))
|
||||
else:
|
||||
from platform import system
|
||||
if system() == 'Linux':
|
||||
self.CalculixBinary = 'ccx'
|
||||
elif system() == 'Windows':
|
||||
self.CalculixBinary = FreeCAD.getHomePath() + 'bin/ccx.exe'
|
||||
else:
|
||||
self.CalculixBinary = 'ccx'
|
||||
|
||||
self.solver_object = solver_object
|
||||
|
||||
self.Calculix = QtCore.QProcess()
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(300)
|
||||
|
||||
self.fem_console_message = ''
|
||||
|
||||
# Connect Signals and Slots
|
||||
QtCore.QObject.connect(self.form.tb_choose_working_dir, QtCore.SIGNAL("clicked()"), self.choose_working_dir)
|
||||
QtCore.QObject.connect(self.form.pb_write_inp, QtCore.SIGNAL("clicked()"), self.write_input_file_handler)
|
||||
QtCore.QObject.connect(self.form.pb_edit_inp, QtCore.SIGNAL("clicked()"), self.editCalculixInputFile)
|
||||
QtCore.QObject.connect(self.form.pb_run_ccx, QtCore.SIGNAL("clicked()"), self.runCalculix)
|
||||
QtCore.QObject.connect(self.form.rb_static_analysis, QtCore.SIGNAL("clicked()"), self.select_static_analysis)
|
||||
QtCore.QObject.connect(self.form.rb_frequency_analysis, QtCore.SIGNAL("clicked()"), self.select_frequency_analysis)
|
||||
QtCore.QObject.connect(self.form.rb_thermomech_analysis, QtCore.SIGNAL("clicked()"), self.select_thermomech_analysis)
|
||||
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("stateChanged(QProcess::ProcessState)"), self.calculixStateChanged)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("error(QProcess::ProcessError)"), self.calculixError)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("finished(int)"), self.calculixFinished)
|
||||
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.UpdateText)
|
||||
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
# only show a close button
|
||||
# def accept() in no longer needed, since there is no OK button
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
if self.solver_object.AnalysisType == 'static':
|
||||
self.form.rb_static_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'frequency':
|
||||
self.form.rb_frequency_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'thermomech':
|
||||
self.form.rb_thermomech_analysis.setChecked(True)
|
||||
return
|
||||
|
||||
def femConsoleMessage(self, message="", color="#000000"):
|
||||
self.fem_console_message = self.fem_console_message + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.textEdit_Output.setText(self.fem_console_message)
|
||||
self.form.textEdit_Output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def printCalculiXstdout(self):
|
||||
out = self.Calculix.readAllStandardOutput()
|
||||
if out.isEmpty():
|
||||
self.femConsoleMessage("CalculiX stdout is empty", "#FF0000")
|
||||
else:
|
||||
try:
|
||||
out = unicode(out, 'utf-8', 'replace')
|
||||
rx = QtCore.QRegExp("\\*ERROR.*\\n\\n")
|
||||
rx.setMinimal(True)
|
||||
pos = rx.indexIn(out)
|
||||
while not pos < 0:
|
||||
match = rx.cap(0)
|
||||
FreeCAD.Console.PrintError(match.strip().replace('\n', ' ') + '\n')
|
||||
pos = rx.indexIn(out, pos + 1)
|
||||
out = os.linesep.join([s for s in out.splitlines() if s])
|
||||
self.femConsoleMessage(out.replace('\n', '<br>'))
|
||||
except UnicodeDecodeError:
|
||||
self.femConsoleMessage("Error converting stdout from CalculiX", "#FF0000")
|
||||
|
||||
def UpdateText(self):
|
||||
if(self.Calculix.state() == QtCore.QProcess.ProcessState.Running):
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def calculixError(self, error):
|
||||
print ("Error() {}".format(error))
|
||||
self.femConsoleMessage("CalculiX execute error: {}".format(error), "#FF0000")
|
||||
|
||||
def calculixStarted(self):
|
||||
print ("calculixStarted()")
|
||||
print (self.Calculix.state())
|
||||
self.form.pb_run_ccx.setText("Break CalculiX")
|
||||
|
||||
def calculixStateChanged(self, newState):
|
||||
if (newState == QtCore.QProcess.ProcessState.Starting):
|
||||
self.femConsoleMessage("Starting CalculiX...")
|
||||
if (newState == QtCore.QProcess.ProcessState.Running):
|
||||
self.femConsoleMessage("CalculiX is running...")
|
||||
if (newState == QtCore.QProcess.ProcessState.NotRunning):
|
||||
self.femConsoleMessage("CalculiX stopped.")
|
||||
|
||||
def calculixFinished(self, exitCode):
|
||||
print ("calculixFinished() {}".format(exitCode))
|
||||
print (self.Calculix.state())
|
||||
|
||||
# Restore previous cwd
|
||||
QtCore.QDir.setCurrent(self.cwd)
|
||||
|
||||
self.printCalculiXstdout()
|
||||
self.Timer.stop()
|
||||
|
||||
self.femConsoleMessage("CalculiX done!", "#00AA00")
|
||||
|
||||
self.form.pb_run_ccx.setText("Re-run CalculiX")
|
||||
self.femConsoleMessage("Loading result sets...")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.reset_mesh_purge_results_checked()
|
||||
fea.inp_file_name = self.inp_file_name
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
try:
|
||||
fea.load_results()
|
||||
except:
|
||||
QApplication.restoreOverrideCursor()
|
||||
majorVersion, minorVersion = fea.get_ccx_version()
|
||||
if majorVersion == 2 and minorVersion <= 10:
|
||||
message = "The used CalculiX version {}.{} creates broken output files.\n" \
|
||||
"Please upgrade to a newer version.".format(majorVersion, minorVersion)
|
||||
QtGui.QMessageBox.warning(None, "Upgrade CalculiX", message)
|
||||
raise
|
||||
else:
|
||||
QApplication.restoreOverrideCursor()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def choose_working_dir(self):
|
||||
current_wd = self.setup_working_dir()
|
||||
wd = QtGui.QFileDialog.getExistingDirectory(None, 'Choose CalculiX working directory',
|
||||
current_wd)
|
||||
if wd:
|
||||
self.solver_object.WorkingDir = wd
|
||||
else:
|
||||
self.solver_object.WorkingDir = current_wd
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
|
||||
def write_input_file_handler(self):
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
QApplication.restoreOverrideCursor()
|
||||
if self.check_prerequisites_helper():
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
self.inp_file_name = ""
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.set_analysis_type(self.solver_object.AnalysisType)
|
||||
fea.update_objects()
|
||||
fea.write_inp_file()
|
||||
if fea.inp_file_name != "":
|
||||
self.inp_file_name = fea.inp_file_name
|
||||
self.femConsoleMessage("Write completed.")
|
||||
self.form.pb_edit_inp.setEnabled(True)
|
||||
self.form.pb_run_ccx.setEnabled(True)
|
||||
else:
|
||||
self.femConsoleMessage("Write .inp file failed!", "#FF0000")
|
||||
QApplication.restoreOverrideCursor()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def check_prerequisites_helper(self):
|
||||
self.Start = time.time()
|
||||
self.femConsoleMessage("Check dependencies...")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.update_objects()
|
||||
message = fea.check_prerequisites()
|
||||
if message != "":
|
||||
QtGui.QMessageBox.critical(None, "Missing prerequisit(s)", message)
|
||||
return False
|
||||
return True
|
||||
|
||||
def start_ext_editor(self, ext_editor_path, filename):
|
||||
if not hasattr(self, "ext_editor_process"):
|
||||
self.ext_editor_process = QtCore.QProcess()
|
||||
if self.ext_editor_process.state() != QtCore.QProcess.Running:
|
||||
self.ext_editor_process.start(ext_editor_path, [filename])
|
||||
|
||||
def editCalculixInputFile(self):
|
||||
print ('editCalculixInputFile {}'.format(self.inp_file_name))
|
||||
if self.ccx_prefs.GetBool("UseInternalEditor", True):
|
||||
FemGui.open(self.inp_file_name)
|
||||
else:
|
||||
ext_editor_path = self.ccx_prefs.GetString("ExternalEditorPath", "")
|
||||
if ext_editor_path:
|
||||
self.start_ext_editor(ext_editor_path, self.inp_file_name)
|
||||
else:
|
||||
print ("External editor is not defined in FEM preferences. Falling back to internal editor")
|
||||
FemGui.open(self.inp_file_name)
|
||||
|
||||
def runCalculix(self):
|
||||
print ('runCalculix')
|
||||
self.Start = time.time()
|
||||
|
||||
self.femConsoleMessage("CalculiX binary: {}".format(self.CalculixBinary))
|
||||
self.femConsoleMessage("Run CalculiX...")
|
||||
|
||||
# run Calculix
|
||||
print ('run CalculiX at: {} with: {}'.format(self.CalculixBinary, os.path.splitext(self.inp_file_name)[0]))
|
||||
# change cwd because ccx may crash if directory has no write permission
|
||||
# there is also a limit of the length of file names so jump to the document directory
|
||||
self.cwd = QtCore.QDir.currentPath()
|
||||
fi = QtCore.QFileInfo(self.inp_file_name)
|
||||
QtCore.QDir.setCurrent(fi.path())
|
||||
self.Calculix.start(self.CalculixBinary, ['-i', fi.baseName()])
|
||||
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def select_analysis_type(self, analysis_type):
|
||||
if self.solver_object.AnalysisType != analysis_type:
|
||||
self.solver_object.AnalysisType = analysis_type
|
||||
self.form.pb_edit_inp.setEnabled(False)
|
||||
self.form.pb_run_ccx.setEnabled(False)
|
||||
|
||||
def select_static_analysis(self):
|
||||
self.select_analysis_type('static')
|
||||
|
||||
def select_frequency_analysis(self):
|
||||
self.select_analysis_type('frequency')
|
||||
|
||||
def select_thermomech_analysis(self):
|
||||
self.select_analysis_type('thermomech')
|
||||
|
||||
# That function overlaps with FemToolsCcx setup_working_dir and could be removed when the one from FemToolsCcx would be used
|
||||
def setup_working_dir(self):
|
||||
wd = self.solver_object.WorkingDir
|
||||
if not (os.path.isdir(wd)):
|
||||
try:
|
||||
os.makedirs(wd)
|
||||
except:
|
||||
print ("Dir \'{}\' from FEM preferences doesn't exist and cannot be created.".format(wd))
|
||||
import tempfile
|
||||
wd = tempfile.gettempdir()
|
||||
print ("Dir \'{}\' will be used instead.".format(wd))
|
||||
return wd
|
||||
@@ -30,11 +30,17 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
import PyObjects._FemElementFluid1D
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemElementFluid1D:
|
||||
"A View Provider for the FemElementFluid1D object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -42,6 +48,7 @@ class _ViewProviderFemElementFluid1D:
|
||||
return ":/icons/fem-fluid-section.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -60,8 +67,7 @@ class _ViewProviderFemElementFluid1D:
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
import PyGui._TaskPanelFemElementFluid1D
|
||||
taskd = PyGui._TaskPanelFemElementFluid1D._TaskPanelFemElementFluid1D(self.Object)
|
||||
taskd = _TaskPanelFemElementFluid1D(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -83,3 +89,385 @@ class _ViewProviderFemElementFluid1D:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemElementFluid1D:
|
||||
'''The TaskPanel for editing References property of FemElementFluid1D objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementFluid1D.ui")
|
||||
QtCore.QObject.connect(self.form.btn_add, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
QtCore.QObject.connect(self.form.btn_remove, QtCore.SIGNAL("clicked()"), self.remove_reference)
|
||||
QtCore.QObject.connect(self.form.cb_section_type, QtCore.SIGNAL("activated(int)"), self.sectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.cb_liquid_section_type, QtCore.SIGNAL("activated(int)"), self.liquidsectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.if_manning_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.manning_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_manning_radius, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.manning_radius_changed)
|
||||
QtCore.QObject.connect(self.form.sb_manning_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.manning_coefficient_changed)
|
||||
QtCore.QObject.connect(self.form.if_enlarge_area1, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.enlarge_area1_changed)
|
||||
QtCore.QObject.connect(self.form.if_enlarge_area2, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.enlarge_area2_changed)
|
||||
QtCore.QObject.connect(self.form.if_contract_area1, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.contract_area1_changed)
|
||||
QtCore.QObject.connect(self.form.if_contract_area2, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.contract_area2_changed)
|
||||
QtCore.QObject.connect(self.form.if_inletpressure, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.inlet_pressure_changed)
|
||||
QtCore.QObject.connect(self.form.if_outletpressure, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.outlet_pressure_changed)
|
||||
QtCore.QObject.connect(self.form.if_inletflowrate, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.inlet_flowrate_changed)
|
||||
QtCore.QObject.connect(self.form.if_outletflowrate, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.outlet_flowrate_changed)
|
||||
QtCore.QObject.connect(self.form.gb_inletpressure, QtCore.SIGNAL("clicked(bool)"), self.inlet_pressure_active)
|
||||
QtCore.QObject.connect(self.form.gb_outletpressure, QtCore.SIGNAL("clicked(bool)"), self.outlet_pressure_active)
|
||||
QtCore.QObject.connect(self.form.gb_inletflowrate, QtCore.SIGNAL("clicked(bool)"), self.inlet_flowrate_active)
|
||||
QtCore.QObject.connect(self.form.gb_outletflowrate, QtCore.SIGNAL("clicked(bool)"), self.outlet_flowrate_active)
|
||||
QtCore.QObject.connect(self.form.if_entrance_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.entrance_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_entrance_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.entrance_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_diaphragm_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.diaphragm_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_diaphragm_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.diaphragm_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_bend_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.bend_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bradius_pdiameter, QtCore.SIGNAL("valueChanged(double)"), self.bradius_pdiameter_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bend_angle, QtCore.SIGNAL("valueChanged(double)"), self.bend_angle_changed)
|
||||
QtCore.QObject.connect(self.form.sb_bend_loss_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.bend_loss_coefficient_changed)
|
||||
QtCore.QObject.connect(self.form.if_gatevalve_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.gatevalve_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.sb_gatevalve_closing_coeff, QtCore.SIGNAL("valueChanged(double)"), self.gatevalve_closing_coeff_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_pipe_area, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_pipe_area_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_radius, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_radius_changed)
|
||||
QtCore.QObject.connect(self.form.if_colebrooke_grain_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.colebrooke_grain_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.sb_colebrooke_form_factor, QtCore.SIGNAL("valueChanged(double)"), self.colebrooke_form_factor_changed)
|
||||
QtCore.QObject.connect(self.form.tw_pump_characteristics, QtCore.SIGNAL("cellChanged(int, int)"), self.pump_characteristics_changed)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
self.form.cb_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_fluid_types)
|
||||
self.form.cb_liquid_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_liquid_types)
|
||||
self.form.cb_gas_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_gas_types)
|
||||
self.form.cb_channel_section_type.addItems(PyObjects._FemElementFluid1D._FemElementFluid1D.known_channel_types)
|
||||
|
||||
self.get_fluidsection_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_fluidsection_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_fluidsection_props(self):
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
self.SectionType = self.obj.SectionType
|
||||
self.LiquidSectionType = self.obj.LiquidSectionType
|
||||
self.ManningArea = self.obj.ManningArea
|
||||
self.ManningRadius = self.obj.ManningRadius
|
||||
self.ManningCoefficient = self.obj.ManningCoefficient
|
||||
self.EnlargeArea1 = self.obj.EnlargeArea1
|
||||
self.EnlargeArea2 = self.obj.EnlargeArea2
|
||||
self.ContractArea1 = self.obj.ContractArea1
|
||||
self.ContractArea2 = self.obj.ContractArea2
|
||||
self.OutletPressure = self.obj.OutletPressure
|
||||
self.InletPressure = self.obj.InletPressure
|
||||
self.OutletFlowRate = self.obj.OutletFlowRate
|
||||
self.InletFlowRate = self.obj.InletFlowRate
|
||||
self.OutletPressureActive = self.obj.OutletPressureActive
|
||||
self.InletPressureActive = self.obj.InletPressureActive
|
||||
self.OutletFlowRateActive = self.obj.OutletFlowRateActive
|
||||
self.InletFlowRateActive = self.obj.InletFlowRateActive
|
||||
self.EntrancePipeArea = self.obj.EntrancePipeArea
|
||||
self.EntranceArea = self.obj.EntranceArea
|
||||
self.DiaphragmPipeArea = self.obj.DiaphragmPipeArea
|
||||
self.DiaphragmArea = self.obj.DiaphragmArea
|
||||
self.BendPipeArea = self.obj.BendPipeArea
|
||||
self.BendRadiusDiameter = self.obj.BendRadiusDiameter
|
||||
self.BendAngle = self.obj.BendAngle
|
||||
self.BendLossCoefficient = self.obj.BendLossCoefficient
|
||||
self.GateValvePipeArea = self.obj.GateValvePipeArea
|
||||
self.GateValveClosingCoeff = self.obj.GateValveClosingCoeff
|
||||
self.ColebrookeArea = self.obj.ColebrookeArea
|
||||
self.ColebrookeRadius = self.obj.ColebrookeRadius
|
||||
self.ColebrookeGrainDiameter = self.obj.ColebrookeGrainDiameter
|
||||
self.ColebrookeFormFactor = self.obj.ColebrookeFormFactor
|
||||
self.PumpFlowRate = self.obj.PumpFlowRate
|
||||
self.PumpHeadLoss = self.obj.PumpHeadLoss
|
||||
|
||||
def set_fluidsection_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.LiquidSectionType = self.LiquidSectionType
|
||||
self.obj.SectionType = self.SectionType
|
||||
self.obj.ManningArea = self.ManningArea
|
||||
self.obj.ManningRadius = self.ManningRadius
|
||||
self.obj.ManningCoefficient = self.ManningCoefficient
|
||||
self.obj.EnlargeArea1 = self.EnlargeArea1
|
||||
self.obj.EnlargeArea2 = self.EnlargeArea2
|
||||
self.obj.ContractArea1 = self.ContractArea1
|
||||
self.obj.ContractArea2 = self.ContractArea2
|
||||
self.obj.OutletPressure = self.OutletPressure
|
||||
self.obj.InletPressure = self.InletPressure
|
||||
self.obj.OutletFlowRate = self.OutletFlowRate
|
||||
self.obj.InletFlowRate = self.InletFlowRate
|
||||
self.obj.OutletPressureActive = self.OutletPressureActive
|
||||
self.obj.InletPressureActive = self.InletPressureActive
|
||||
self.obj.OutletFlowRateActive = self.OutletFlowRateActive
|
||||
self.obj.InletFlowRateActive = self.InletFlowRateActive
|
||||
self.obj.EntrancePipeArea = self.EntrancePipeArea
|
||||
self.obj.EntranceArea = self.EntranceArea
|
||||
self.obj.DiaphragmPipeArea = self.DiaphragmPipeArea
|
||||
self.obj.DiaphragmArea = self.DiaphragmArea
|
||||
self.obj.BendPipeArea = self.BendPipeArea
|
||||
self.obj.BendRadiusDiameter = self.BendRadiusDiameter
|
||||
self.obj.BendAngle = self.BendAngle
|
||||
self.obj.BendLossCoefficient = self.BendLossCoefficient
|
||||
self.obj.GateValvePipeArea = self.GateValvePipeArea
|
||||
self.obj.GateValveClosingCoeff = self.GateValveClosingCoeff
|
||||
self.obj.ColebrookeArea = self.ColebrookeArea
|
||||
self.obj.ColebrookeRadius = self.ColebrookeRadius
|
||||
self.obj.ColebrookeGrainDiameter = self.ColebrookeGrainDiameter
|
||||
self.obj.ColebrookeFormFactor = self.ColebrookeFormFactor
|
||||
self.obj.PumpFlowRate = self.PumpFlowRate
|
||||
self.obj.PumpHeadLoss = self.PumpHeadLoss
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
index_sectiontype = self.form.cb_section_type.findText(self.SectionType)
|
||||
self.form.cb_section_type.setCurrentIndex(index_sectiontype)
|
||||
self.form.sw_section_type.setCurrentIndex(index_sectiontype)
|
||||
index_liquidsectiontype = self.form.cb_liquid_section_type.findText(self.LiquidSectionType)
|
||||
self.form.cb_liquid_section_type.setCurrentIndex(index_liquidsectiontype)
|
||||
self.form.sw_liquid_section_type.setCurrentIndex(index_liquidsectiontype)
|
||||
self.form.if_manning_area.setText(self.ManningArea.UserString)
|
||||
self.form.if_manning_radius.setText(self.ManningRadius.UserString)
|
||||
self.form.sb_manning_coefficient.setValue(self.ManningCoefficient)
|
||||
self.form.if_enlarge_area1.setText(self.EnlargeArea1.UserString)
|
||||
self.form.if_enlarge_area2.setText(self.EnlargeArea2.UserString)
|
||||
self.form.if_contract_area1.setText(self.ContractArea1.UserString)
|
||||
self.form.if_contract_area2.setText(self.ContractArea2.UserString)
|
||||
self.form.if_inletpressure.setText(FreeCAD.Units.Quantity(1000 * self.InletPressure, FreeCAD.Units.Pressure).UserString)
|
||||
self.form.if_outletpressure.setText(FreeCAD.Units.Quantity(1000 * self.OutletPressure, FreeCAD.Units.Pressure).UserString)
|
||||
self.form.if_inletflowrate.setText(str(self.InletFlowRate))
|
||||
self.form.if_outletflowrate.setText(str(self.OutletFlowRate))
|
||||
self.form.gb_inletpressure.setChecked(self.InletPressureActive)
|
||||
self.form.gb_outletpressure.setChecked(self.OutletPressureActive)
|
||||
self.form.gb_inletflowrate.setChecked(self.InletFlowRateActive)
|
||||
self.form.gb_outletflowrate.setChecked(self.OutletFlowRateActive)
|
||||
self.form.if_entrance_pipe_area.setText(self.EntrancePipeArea.UserString)
|
||||
self.form.if_entrance_area.setText(self.EntranceArea.UserString)
|
||||
self.form.if_diaphragm_pipe_area.setText(self.DiaphragmPipeArea.UserString)
|
||||
self.form.if_diaphragm_area.setText(self.DiaphragmArea.UserString)
|
||||
self.form.if_bend_pipe_area.setText(self.BendPipeArea.UserString)
|
||||
self.form.sb_bradius_pdiameter.setValue(self.BendRadiusDiameter)
|
||||
self.form.sb_bend_angle.setValue(self.BendAngle)
|
||||
self.form.sb_bend_loss_coefficient.setValue(self.BendLossCoefficient)
|
||||
self.form.if_gatevalve_pipe_area.setText(self.GateValvePipeArea.UserString)
|
||||
self.form.sb_gatevalve_closing_coeff.setValue(self.GateValveClosingCoeff)
|
||||
self.form.if_colebrooke_pipe_area.setText(self.ColebrookeArea.UserString)
|
||||
self.form.if_colebrooke_radius.setText(self.ColebrookeRadius.UserString)
|
||||
self.form.if_colebrooke_grain_diameter.setText(self.ColebrookeGrainDiameter.UserString)
|
||||
self.form.sb_colebrooke_form_factor.setValue(self.ColebrookeFormFactor)
|
||||
for i in range(len(self.PumpFlowRate)):
|
||||
self.form.tw_pump_characteristics.setItem(i, 0, QtGui.QTableWidgetItem(str(self.PumpFlowRate[i])))
|
||||
self.form.tw_pump_characteristics.setItem(i, 1, QtGui.QTableWidgetItem(str(self.PumpHeadLoss[i])))
|
||||
self.rebuild_list_References()
|
||||
|
||||
def sectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_section_type.setCurrentIndex(index)
|
||||
self.form.sw_section_type.setCurrentIndex(index)
|
||||
self.SectionType = str(self.form.cb_section_type.itemText(index)) # form returns unicode
|
||||
|
||||
def liquidsectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_liquid_section_type.setCurrentIndex(index)
|
||||
self.form.sw_liquid_section_type.setCurrentIndex(index)
|
||||
self.LiquidSectionType = str(self.form.cb_liquid_section_type.itemText(index)) # form returns unicode
|
||||
|
||||
def manning_area_changed(self, base_quantity_value):
|
||||
self.ManningArea = base_quantity_value
|
||||
|
||||
def manning_radius_changed(self, base_quantity_value):
|
||||
self.ManningRadius = base_quantity_value
|
||||
|
||||
def manning_coefficient_changed(self, base_quantity_value):
|
||||
self.ManningCoefficient = base_quantity_value
|
||||
|
||||
def enlarge_area1_changed(self, base_quantity_value):
|
||||
self.EnlargeArea1 = base_quantity_value
|
||||
|
||||
def enlarge_area2_changed(self, base_quantity_value):
|
||||
self.EnlargeArea2 = base_quantity_value
|
||||
|
||||
def contract_area1_changed(self, base_quantity_value):
|
||||
self.ContractArea1 = base_quantity_value
|
||||
|
||||
def contract_area2_changed(self, base_quantity_value):
|
||||
self.ContractArea2 = base_quantity_value
|
||||
|
||||
def inlet_pressure_changed(self, base_quantity_value):
|
||||
self.InletPressure = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("MPa"))
|
||||
|
||||
def outlet_pressure_changed(self, base_quantity_value):
|
||||
self.OutletPressure = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("MPa"))
|
||||
|
||||
def inlet_flowrate_changed(self, base_quantity_value):
|
||||
self.InletFlowRate = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("kg/s"))
|
||||
|
||||
def outlet_flowrate_changed(self, base_quantity_value):
|
||||
self.OutletFlowRate = float(FreeCAD.Units.Quantity(base_quantity_value).getValueAs("kg/s"))
|
||||
|
||||
def inlet_pressure_active(self, active):
|
||||
self.InletPressureActive = active
|
||||
|
||||
def outlet_pressure_active(self, active):
|
||||
self.OutletPressureActive = active
|
||||
|
||||
def inlet_flowrate_active(self, active):
|
||||
self.InletFlowRateActive = active
|
||||
|
||||
def outlet_flowrate_active(self, active):
|
||||
self.OutletFlowRateActive = active
|
||||
|
||||
def entrance_pipe_area_changed(self, base_quantity_value):
|
||||
self.EntrancePipeArea = base_quantity_value
|
||||
|
||||
def entrance_area_changed(self, base_quantity_value):
|
||||
self.EntranceArea = base_quantity_value
|
||||
|
||||
def diaphragm_pipe_area_changed(self, base_quantity_value):
|
||||
self.DiaphragmPipeArea = base_quantity_value
|
||||
|
||||
def diaphragm_area_changed(self, base_quantity_value):
|
||||
self.DiaphragmArea = base_quantity_value
|
||||
|
||||
def bend_pipe_area_changed(self, base_quantity_value):
|
||||
self.BendPipeArea = base_quantity_value
|
||||
|
||||
def bradius_pdiameter_changed(self, base_quantity_value):
|
||||
self.BendRadiusDiameter = base_quantity_value
|
||||
|
||||
def bend_angle_changed(self, base_quantity_value):
|
||||
self.BendAngle = base_quantity_value
|
||||
|
||||
def bend_loss_coefficient_changed(self, base_quantity_value):
|
||||
self.BendLossCoefficient = base_quantity_value
|
||||
|
||||
def gatevalve_pipe_area_changed(self, base_quantity_value):
|
||||
self.GateValvePipeArea = base_quantity_value
|
||||
|
||||
def gatevalve_closing_coeff_changed(self, base_quantity_value):
|
||||
self.GateValveClosingCoeff = base_quantity_value
|
||||
|
||||
def colebrooke_pipe_area_changed(self, base_quantity_value):
|
||||
self.ColebrookeArea = base_quantity_value
|
||||
|
||||
def colebrooke_radius_changed(self, base_quantity_value):
|
||||
self.ColebrookeRadius = base_quantity_value
|
||||
|
||||
def colebrooke_grain_diameter_changed(self, base_quantity_value):
|
||||
self.ColebrookeGrainDiameter = base_quantity_value
|
||||
|
||||
def colebrooke_form_factor_changed(self, base_quantity_value):
|
||||
self.ColebrookeFormFactor = base_quantity_value
|
||||
|
||||
def pump_characteristics_changed(self, row, column):
|
||||
if column == 0:
|
||||
self.PumpFlowRate[row] = float(self.form.tw_pump_characteristics.item(row, column).text())
|
||||
else:
|
||||
self.PumpHeadLoss[row] = float(self.form.tw_pump_characteristics.item(row, column).text())
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Edges by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Edge':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -29,11 +29,17 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
import PyObjects._FemElementGeometry1D
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemElementGeometry1D:
|
||||
"A View Provider for the FemElementGeometry1D object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -41,6 +47,7 @@ class _ViewProviderFemElementGeometry1D:
|
||||
return ":/icons/fem-beam-section.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -59,8 +66,7 @@ class _ViewProviderFemElementGeometry1D:
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
import PyGui._TaskPanelFemElementGeometry1D
|
||||
taskd = PyGui._TaskPanelFemElementGeometry1D._TaskPanelFemElementGeometry1D(self.Object)
|
||||
taskd = _TaskPanelFemElementGeometry1D(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -82,3 +88,185 @@ class _ViewProviderFemElementGeometry1D:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemElementGeometry1D:
|
||||
'''The TaskPanel for editing References property of FemElementGeometry1D objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementGeometry1D.ui")
|
||||
QtCore.QObject.connect(self.form.cb_crosssectiontype, QtCore.SIGNAL("activated(int)"), self.sectiontype_changed)
|
||||
QtCore.QObject.connect(self.form.if_rec_height, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.rec_height_changed)
|
||||
QtCore.QObject.connect(self.form.if_rec_width, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.rec_width_changed)
|
||||
QtCore.QObject.connect(self.form.if_circ_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.circ_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.if_pipe_diameter, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.pipe_diameter_changed)
|
||||
QtCore.QObject.connect(self.form.if_pipe_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.pipe_thickness_changed)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.form.cb_crosssectiontype.addItems(PyObjects._FemElementGeometry1D._FemElementGeometry1D.known_beam_types) # it is inside the class thus double _FemElementGeometry1D
|
||||
|
||||
self.get_beamsection_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_beamsection_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_beamsection_props(self):
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
self.SectionType = self.obj.SectionType
|
||||
self.RectHeight = self.obj.RectHeight
|
||||
self.RectWidth = self.obj.RectWidth
|
||||
self.CircDiameter = self.obj.CircDiameter
|
||||
self.PipeDiameter = self.obj.PipeDiameter
|
||||
self.PipeThickness = self.obj.PipeThickness
|
||||
|
||||
def set_beamsection_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.SectionType = self.SectionType
|
||||
self.obj.RectHeight = self.RectHeight
|
||||
self.obj.RectWidth = self.RectWidth
|
||||
self.obj.CircDiameter = self.CircDiameter
|
||||
self.obj.PipeDiameter = self.PipeDiameter
|
||||
self.obj.PipeThickness = self.PipeThickness
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
index_crosssectiontype = self.form.cb_crosssectiontype.findText(self.SectionType)
|
||||
self.form.cb_crosssectiontype.setCurrentIndex(index_crosssectiontype)
|
||||
self.form.if_rec_height.setText(self.RectHeight.UserString)
|
||||
self.form.if_rec_width.setText(self.RectWidth.UserString)
|
||||
self.form.if_circ_diameter.setText(self.CircDiameter.UserString)
|
||||
self.form.if_pipe_diameter.setText(self.PipeDiameter.UserString)
|
||||
self.form.if_pipe_thickness.setText(self.PipeThickness.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def sectiontype_changed(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_crosssectiontype.setCurrentIndex(index)
|
||||
self.SectionType = str(self.form.cb_crosssectiontype.itemText(index)) # form returns unicode
|
||||
|
||||
def rec_height_changed(self, base_quantity_value):
|
||||
self.RectHeight = base_quantity_value
|
||||
|
||||
def rec_width_changed(self, base_quantity_value):
|
||||
self.RectWidth = base_quantity_value
|
||||
|
||||
def circ_diameter_changed(self, base_quantity_value):
|
||||
self.CircDiameter = base_quantity_value
|
||||
|
||||
def pipe_diameter_changed(self, base_quantity_value):
|
||||
self.PipeDiameter = base_quantity_value
|
||||
|
||||
def pipe_thickness_changed(self, base_quantity_value):
|
||||
self.PipeThickness = base_quantity_value
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Edges by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Edge':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -29,11 +29,16 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemElementGeometry2D:
|
||||
"A View Provider for the FemElementGeometry2D object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -41,6 +46,7 @@ class _ViewProviderFemElementGeometry2D:
|
||||
return ":/icons/fem-shell-thickness.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -59,8 +65,7 @@ class _ViewProviderFemElementGeometry2D:
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
import PyGui._TaskPanelFemElementGeometry2D
|
||||
taskd = PyGui._TaskPanelFemElementGeometry2D._TaskPanelFemElementGeometry2D(self.Object)
|
||||
taskd = _TaskPanelFemElementGeometry2D(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -82,3 +87,144 @@ class _ViewProviderFemElementGeometry2D:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemElementGeometry2D:
|
||||
'''The TaskPanel for editing References property of FemElementGeometry2D objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemElementGeometry2D.ui")
|
||||
QtCore.QObject.connect(self.form.if_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.thickness_changed)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_shellthickness_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_shellthickness_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_shellthickness_props(self):
|
||||
self.thickness = self.obj.Thickness
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_shellthickness_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.Thickness = self.thickness
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_thickness.setText(self.thickness.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def thickness_changed(self, base_quantity_value):
|
||||
self.thickness = base_quantity_value
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
print_message = "Select Faces by single click on them to add them to the list"
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
# print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape"):
|
||||
if selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if elt.ShapeType == 'Face':
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -31,6 +31,17 @@ import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
|
||||
# for the panel
|
||||
from FreeCAD import Units
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide.QtGui import QFileDialog
|
||||
from PySide.QtGui import QMessageBox
|
||||
import sys
|
||||
if sys.version_info.major >= 3:
|
||||
unicode = str
|
||||
|
||||
|
||||
class _ViewProviderFemMaterial:
|
||||
"A View Provider for the FemMaterial object"
|
||||
|
||||
@@ -51,8 +62,7 @@ class _ViewProviderFemMaterial:
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
import PyGui._TaskPanelFemMaterial
|
||||
taskd = PyGui._TaskPanelFemMaterial._TaskPanelFemMaterial(self.Object)
|
||||
taskd = _TaskPanelFemMaterial(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -75,3 +85,608 @@ class _ViewProviderFemMaterial:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemMaterial:
|
||||
'''The editmode TaskPanel for FemMaterial objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces and Edges by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
self.material = self.obj.Material
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMaterial.ui")
|
||||
QtCore.QObject.connect(self.form.pushButton_MatWeb, QtCore.SIGNAL("clicked()"), self.goto_MatWeb)
|
||||
QtCore.QObject.connect(self.form.pushButton_saveas, QtCore.SIGNAL("clicked()"), self.export_material)
|
||||
QtCore.QObject.connect(self.form.cb_materials, QtCore.SIGNAL("activated(int)"), self.choose_material)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
# basic properties must be provided
|
||||
QtCore.QObject.connect(self.form.input_fd_density, QtCore.SIGNAL("valueChanged(double)"), self.density_changed)
|
||||
# mechanical properties
|
||||
QtCore.QObject.connect(self.form.input_fd_young_modulus, QtCore.SIGNAL("valueChanged(double)"), self.ym_changed)
|
||||
QtCore.QObject.connect(self.form.spinBox_poisson_ratio, QtCore.SIGNAL("valueChanged(double)"), self.pr_changed)
|
||||
# thermal properties
|
||||
QtCore.QObject.connect(self.form.input_fd_thermal_conductivity, QtCore.SIGNAL("valueChanged(double)"), self.tc_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_expansion_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.tec_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_specific_heat, QtCore.SIGNAL("valueChanged(double)"), self.sh_changed)
|
||||
# fluidic properties, only volumetric thermal expansion coeff makes sense
|
||||
QtCore.QObject.connect(self.form.input_fd_kinematic_viscosity, QtCore.SIGNAL("valueChanged(double)"), self.kinematic_viscosity_changed)
|
||||
QtCore.QObject.connect(self.form.input_fd_vol_expansion_coefficient, QtCore.SIGNAL("valueChanged(double)"), self.vtec_changed)
|
||||
|
||||
# hide some groupBox according to material category
|
||||
self.form.label_category.setText(self.obj.Category)
|
||||
if self.obj.Category == 'Fluid':
|
||||
self.form.groupBox_mechanical.setVisible(0)
|
||||
self.form.label_expansion_coefficient.setVisible(0)
|
||||
self.form.input_fd_expansion_coefficient.setVisible(0)
|
||||
else:
|
||||
self.form.groupBox_fluidic.setVisible(0)
|
||||
self.form.label_vol_expansion_coefficient.setVisible(0)
|
||||
self.form.input_fd_vol_expansion_coefficient.setVisible(0)
|
||||
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.import_materials()
|
||||
previous_mat_path = self.get_material_path(self.material)
|
||||
if not previous_mat_path:
|
||||
material_name = self.get_material_name(self.material)
|
||||
if material_name != 'None':
|
||||
FreeCAD.Console.PrintMessage("Previously used material cannot be found in material directories. Using transient material.\n")
|
||||
self.add_transient_material(self.material)
|
||||
index = self.form.cb_materials.findData(material_name)
|
||||
else:
|
||||
if not self.material:
|
||||
index = self.form.cb_materials.findText(material_name)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("None material was previously used. Reload values.\n")
|
||||
self.add_transient_material(self.material)
|
||||
index = self.form.cb_materials.findData(material_name)
|
||||
self.choose_material(index)
|
||||
else:
|
||||
index = self.form.cb_materials.findData(previous_mat_path)
|
||||
self.choose_material(index)
|
||||
self.has_equal_references_shape_types()
|
||||
self.rebuild_list_References()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
# print(self.material)
|
||||
self.remove_active_sel_server()
|
||||
if self.has_equal_references_shape_types():
|
||||
self.obj.Material = self.material
|
||||
self.obj.References = self.references
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
doc.Document.recompute()
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.remove_active_sel_server()
|
||||
doc = FreeCADGui.getDocument(self.obj.Document)
|
||||
doc.resetEdit()
|
||||
|
||||
def remove_active_sel_server(self):
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def has_equal_references_shape_types(self):
|
||||
import femmesh.meshtools as FemMeshTools
|
||||
ref_shty = ''
|
||||
for ref in self.references:
|
||||
r = FemMeshTools.get_element(ref[0], ref[1]) # the method getElement(element) does not return Solid elements
|
||||
# print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1])
|
||||
if not ref_shty:
|
||||
ref_shty = r.ShapeType
|
||||
if r.ShapeType != ref_shty:
|
||||
message = 'Multiple shape types are not allowed in the reference list.\n'
|
||||
FreeCAD.Console.PrintError(message)
|
||||
QMessageBox.critical(None, "Multiple ShapeTypes not allowed", message)
|
||||
return False
|
||||
return True
|
||||
|
||||
def goto_MatWeb(self):
|
||||
import webbrowser
|
||||
webbrowser.open("http://matweb.com")
|
||||
|
||||
def check_material_keys(self):
|
||||
if 'Density' in self.material:
|
||||
if 'Density' not in str(Units.Unit(self.material['Density'])):
|
||||
print('Density in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['Density'] = '0 kg/m^3'
|
||||
else:
|
||||
print('Density not found in material data of: ' + self.material['Name'])
|
||||
self.material['Density'] = '0 kg/m^3'
|
||||
if self.obj.Category == 'Solid':
|
||||
# mechanical properties
|
||||
if 'YoungsModulus' in self.material:
|
||||
if 'Pressure' not in str(Units.Unit(self.material['YoungsModulus'])): # unit type of YoungsModulus is Pressure
|
||||
print('YoungsModulus in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['YoungsModulus'] = '0 MPa'
|
||||
else:
|
||||
print('YoungsModulus not found in material data of: ' + self.material['Name'])
|
||||
self.material['YoungsModulus'] = '0 MPa'
|
||||
if 'PoissonRatio' not in self.material: # PoissonRatio does not have a unit, we do not gone check for a unit
|
||||
print('PoissonRatio not found in material data of: ' + self.material['Name'])
|
||||
self.material['PoissonRatio'] = '0'
|
||||
if self.obj.Category == 'Fluid':
|
||||
# Fluidic properties
|
||||
if 'KinematicViscosity' in self.material:
|
||||
if 'KinematicViscosity' not in str(Units.Unit(self.material['KinematicViscosity'])):
|
||||
print('KinematicViscosity in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['KinematicViscosity'] = '0 m^2/s'
|
||||
else:
|
||||
print('KinematicViscosity not found in material data of: ' + self.material['Name'])
|
||||
self.material['KinematicViscosity'] = '0 m^2/s'
|
||||
if 'VolumetricThermalExpansionCoefficient' in self.material:
|
||||
if 'ThermalExpansionCoefficient' not in str(Units.Unit(self.material['VolumetricThermalExpansionCoefficient'])): # unit type of VolumetricThermalExpansionCoefficient is ThermalExpansionCoefficient
|
||||
print('VolumetricThermalExpansionCoefficient in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
|
||||
else:
|
||||
print('VolumetricThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
|
||||
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
|
||||
# Thermal properties
|
||||
if 'ThermalConductivity' in self.material:
|
||||
if 'ThermalConductivity' not in str(Units.Unit(self.material['ThermalConductivity'])):
|
||||
print('ThermalConductivity in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['ThermalConductivity'] = '0 W/m/K'
|
||||
else:
|
||||
print('ThermalConductivity not found in material data of: ' + self.material['Name'])
|
||||
self.material['ThermalConductivity'] = '0 W/m/K'
|
||||
if 'ThermalExpansionCoefficient' in self.material:
|
||||
if 'ThermalExpansionCoefficient' not in str(Units.Unit(self.material['ThermalExpansionCoefficient'])):
|
||||
print('ThermalExpansionCoefficient in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
|
||||
else:
|
||||
print('ThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
|
||||
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
|
||||
if 'SpecificHeat' in self.material:
|
||||
if 'SpecificHeat' not in str(Units.Unit(self.material['SpecificHeat'])):
|
||||
print('SpecificHeat in material data seams to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
|
||||
self.material['SpecificHeat'] = '0 J/kg/K'
|
||||
else:
|
||||
print('SpecificHeat not found in material data of: ' + self.material['Name'])
|
||||
self.material['SpecificHeat'] = '0 J/kg/K'
|
||||
|
||||
def ym_changed(self, value):
|
||||
# FreeCADs standard unit for stress is kPa
|
||||
old_ym = Units.Quantity(self.material['YoungsModulus']).getValueAs("kPa")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_ym) / value < 1 + variation):
|
||||
# YoungsModulus has changed
|
||||
material = self.material
|
||||
material['YoungsModulus'] = unicode(value) + " kPa"
|
||||
self.material = material
|
||||
|
||||
def density_changed(self, value):
|
||||
# FreeCADs standard unit for density is kg/mm^3
|
||||
old_density = Units.Quantity(self.material['Density']).getValueAs("kg/m^3")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_density) / value < 1 + variation):
|
||||
# density has changed
|
||||
material = self.material
|
||||
value_in_kg_per_m3 = value * 1e9
|
||||
material['Density'] = unicode(value_in_kg_per_m3) + " kg/m^3" # SvdW:Keep density in SI units for easier readability
|
||||
self.material = material
|
||||
|
||||
def pr_changed(self, value):
|
||||
old_pr = Units.Quantity(self.material['PoissonRatio'])
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_pr) / value < 1 + variation):
|
||||
# PoissonRatio has changed
|
||||
material = self.material
|
||||
material['PoissonRatio'] = unicode(value)
|
||||
self.material = material
|
||||
|
||||
def tc_changed(self, value):
|
||||
old_tc = Units.Quantity(self.material['ThermalConductivity']).getValueAs("W/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_tc) / value < 1 + variation):
|
||||
# ThermalConductivity has changed
|
||||
material = self.material
|
||||
value_in_W_per_mK = value * 1e-3 # To compensate for use of SI units
|
||||
material['ThermalConductivity'] = unicode(value_in_W_per_mK) + " W/m/K"
|
||||
self.material = material
|
||||
|
||||
def tec_changed(self, value):
|
||||
old_tec = Units.Quantity(self.material['ThermalExpansionCoefficient']).getValueAs("um/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_tec) / value < 1 + variation):
|
||||
# ThermalExpansionCoefficient has changed
|
||||
material = self.material
|
||||
value_in_um_per_mK = value * 1e6 # To compensate for use of SI units
|
||||
material['ThermalExpansionCoefficient'] = unicode(value_in_um_per_mK) + " um/m/K"
|
||||
self.material = material
|
||||
|
||||
def sh_changed(self, value):
|
||||
old_sh = Units.Quantity(self.material['SpecificHeat']).getValueAs("J/kg/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_sh) / value < 1 + variation):
|
||||
# SpecificHeat has changed
|
||||
material = self.material
|
||||
value_in_J_per_kgK = value * 1e-6 # To compensate for use of SI units
|
||||
material['SpecificHeat'] = unicode(value_in_J_per_kgK) + " J/kg/K"
|
||||
self.material = material
|
||||
|
||||
################ fluidic #########################
|
||||
def vtec_changed(self, value):
|
||||
old_vtec = Units.Quantity(self.material['VolumetricThermalExpansionCoefficient']).getValueAs("m/m/K")
|
||||
variation = 0.001
|
||||
if value:
|
||||
if not (1 - variation < float(old_vtec) / value < 1 + variation):
|
||||
# VolumetricThermalExpansionCoefficient has changed
|
||||
material = self.material
|
||||
value_in_one_per_K = value
|
||||
material['VolumetricThermalExpansionCoefficient'] = unicode(value_in_one_per_K) + " m/m/K"
|
||||
self.material = material
|
||||
|
||||
def kinematic_viscosity_changed(self, value):
|
||||
old_nu = Units.Quantity(self.material['KinematicViscosity']).getValueAs("m^2/s")
|
||||
variation = 0.000001
|
||||
if value:
|
||||
if not (1 - variation < float(old_nu) / value < 1 + variation):
|
||||
# KinematicViscosity has changed
|
||||
material = self.material
|
||||
value_in_m2_per_second = value
|
||||
material['KinematicViscosity'] = unicode(value_in_m2_per_second) + " m^2/s"
|
||||
self.material = material
|
||||
|
||||
def choose_material(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
mat_file_path = self.form.cb_materials.itemData(index)
|
||||
self.material = self.materials[mat_file_path]
|
||||
self.form.cb_materials.setCurrentIndex(index)
|
||||
self.check_material_keys()
|
||||
self.set_mat_params_in_combo_box(self.material)
|
||||
gen_mat_desc = ""
|
||||
if 'Description' in self.material:
|
||||
gen_mat_desc = self.material['Description']
|
||||
self.form.l_mat_description.setText(gen_mat_desc)
|
||||
|
||||
def get_material_name(self, material):
|
||||
if 'Name' in self.material:
|
||||
return self.material['Name']
|
||||
else:
|
||||
return 'None'
|
||||
|
||||
def get_material_path(self, material):
|
||||
for a_mat in self.materials:
|
||||
unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items())
|
||||
if len(unmatched_items) == 0:
|
||||
return a_mat
|
||||
return ""
|
||||
|
||||
def set_mat_params_in_combo_box(self, matmap):
|
||||
if 'YoungsModulus' in matmap:
|
||||
ym_new_unit = "MPa"
|
||||
ym = FreeCAD.Units.Quantity(matmap['YoungsModulus'])
|
||||
ym_with_new_unit = ym.getValueAs(ym_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(ym_with_new_unit, ym_new_unit))
|
||||
self.form.input_fd_young_modulus.setText(q.UserString)
|
||||
if 'PoissonRatio' in matmap:
|
||||
self.form.spinBox_poisson_ratio.setValue(float(matmap['PoissonRatio']))
|
||||
# Fluidic properties
|
||||
if 'KinematicViscosity' in matmap:
|
||||
nu_new_unit = "m^2/s"
|
||||
nu = FreeCAD.Units.Quantity(matmap['KinematicViscosity'])
|
||||
nu_with_new_unit = nu.getValueAs(nu_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(nu_with_new_unit, nu_new_unit))
|
||||
self.form.input_fd_kinematic_viscosity.setText(q.UserString)
|
||||
# For isotropic materials the volumetric thermal expansion coefficient is three times the linear coefficient:
|
||||
if 'VolumetricThermalExpansionCoefficient' in matmap: # linear, only for solid
|
||||
vtec_new_unit = "m/m/K"
|
||||
vtec = FreeCAD.Units.Quantity(matmap['VolumetricThermalExpansionCoefficient'])
|
||||
vtec_with_new_unit = vtec.getValueAs(vtec_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(vtec_with_new_unit, vtec_new_unit))
|
||||
self.form.input_fd_vol_expansion_coefficient.setText(q.UserString)
|
||||
if 'Density' in matmap:
|
||||
density_new_unit = "kg/m^3"
|
||||
density = FreeCAD.Units.Quantity(matmap['Density'])
|
||||
density_with_new_unit = density.getValueAs(density_new_unit)
|
||||
#self.form.input_fd_density.setText("{} {}".format(density_with_new_unit, density_new_unit))
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(density_with_new_unit, density_new_unit))
|
||||
self.form.input_fd_density.setText(q.UserString)
|
||||
# thermal properties
|
||||
if 'ThermalConductivity' in matmap:
|
||||
tc_new_unit = "W/m/K"
|
||||
tc = FreeCAD.Units.Quantity(matmap['ThermalConductivity'])
|
||||
tc_with_new_unit = tc.getValueAs(tc_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(tc_with_new_unit, tc_new_unit))
|
||||
self.form.input_fd_thermal_conductivity.setText(q.UserString)
|
||||
if 'ThermalExpansionCoefficient' in matmap: # linear, only for solid
|
||||
tec_new_unit = "um/m/K"
|
||||
tec = FreeCAD.Units.Quantity(matmap['ThermalExpansionCoefficient'])
|
||||
tec_with_new_unit = tec.getValueAs(tec_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(tec_with_new_unit, tec_new_unit))
|
||||
self.form.input_fd_expansion_coefficient.setText(q.UserString)
|
||||
if 'SpecificHeat' in matmap:
|
||||
sh_new_unit = "J/kg/K"
|
||||
sh = FreeCAD.Units.Quantity(matmap['SpecificHeat'])
|
||||
sh_with_new_unit = sh.getValueAs(sh_new_unit)
|
||||
q = FreeCAD.Units.Quantity("{} {}".format(sh_with_new_unit, sh_new_unit))
|
||||
self.form.input_fd_specific_heat.setText(q.UserString)
|
||||
|
||||
def add_transient_material(self, material):
|
||||
material_name = self.get_material_name(material)
|
||||
self.form.cb_materials.addItem(QtGui.QIcon(":/icons/help-browser.svg"), material_name, material_name)
|
||||
self.materials[material_name] = material
|
||||
|
||||
######################## material import and export ###################
|
||||
def import_materials(self):
|
||||
self.materials = {}
|
||||
self.pathList = []
|
||||
self.form.cb_materials.clear()
|
||||
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
if self.obj.Category == 'Fluid':
|
||||
self.import_fluid_materials()
|
||||
else:
|
||||
self.import_solid_materials()
|
||||
|
||||
def import_solid_materials(self):
|
||||
use_built_in_materials = self.fem_prefs.GetBool("UseBuiltInMaterials", True)
|
||||
if use_built_in_materials:
|
||||
system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/StandardMaterial"
|
||||
self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg")
|
||||
|
||||
use_mat_from_config_dir = self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True)
|
||||
if use_mat_from_config_dir:
|
||||
user_mat_dirname = FreeCAD.getUserAppDataDir() + "Materials"
|
||||
self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg")
|
||||
|
||||
use_mat_from_custom_dir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
if use_mat_from_custom_dir:
|
||||
custom_mat_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
|
||||
|
||||
def import_fluid_materials(self):
|
||||
#use_built_in_materials = self.fem_prefs.GetBool("UseBuiltInMaterials", True)
|
||||
#if use_built_in_materials:
|
||||
system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/FluidMaterial"
|
||||
self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg")
|
||||
|
||||
use_mat_from_config_dir = self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True)
|
||||
if use_mat_from_config_dir:
|
||||
user_mat_dirname = FreeCAD.getUserAppDataDir() + "FluidMaterial"
|
||||
self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg")
|
||||
|
||||
use_mat_from_custom_dir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
if use_mat_from_custom_dir:
|
||||
custom_mat_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
|
||||
|
||||
def add_mat_dir(self, mat_dir, icon):
|
||||
import glob
|
||||
import os
|
||||
import Material
|
||||
mat_file_extension = ".FCMat"
|
||||
ext_len = len(mat_file_extension)
|
||||
dir_path_list = glob.glob(mat_dir + '/*' + mat_file_extension)
|
||||
self.pathList = self.pathList + dir_path_list
|
||||
material_name_list = []
|
||||
for a_path in dir_path_list:
|
||||
material_name = os.path.basename(a_path[:-ext_len])
|
||||
self.materials[a_path] = Material.importFCMat(a_path)
|
||||
material_name_list.append([material_name, a_path])
|
||||
material_name_list.sort()
|
||||
for mat in material_name_list:
|
||||
self.form.cb_materials.addItem(QtGui.QIcon(icon), mat[0], mat[1])
|
||||
|
||||
def export_FCMat(self, fileName, matDict):
|
||||
"""
|
||||
Write a material dictionary to a FCMat file, a version without group support, with Python3
|
||||
<https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Material/Material.py>
|
||||
"""
|
||||
try:
|
||||
import ConfigParser as configparser
|
||||
except:
|
||||
import configparser # Python 3
|
||||
# himport string
|
||||
Config = configparser.ConfigParser()
|
||||
Config.optionxform = str # disable conversion all uppercase leter in key into lower case
|
||||
|
||||
# ignore creating group, just fill all into group 'FCMat'
|
||||
grp = 'FCMat'
|
||||
if not Config.has_section(grp):
|
||||
Config.add_section(grp)
|
||||
for x in matDict.keys():
|
||||
Config.set(grp, x, matDict[x])
|
||||
|
||||
Preamble = "# This is a FreeCAD material-card file\n\n"
|
||||
# Writing our configuration file to 'example.cfg'
|
||||
with open(fileName, 'wb') as configfile:
|
||||
configfile.write(Preamble)
|
||||
Config.write(configfile)
|
||||
|
||||
def export_material(self):
|
||||
import os
|
||||
if self.obj.Category == 'Fluid':
|
||||
MaterialDir = 'FluidMaterial'
|
||||
else:
|
||||
MaterialDir = 'Material'
|
||||
_UseMaterialsFromCustomDir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True)
|
||||
_dir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
if _UseMaterialsFromCustomDir and _dir != "" and os.path.isdir(_dir):
|
||||
TargetDir = self.fem_prefs.GetString("CustomMaterialsDir", "")
|
||||
elif self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True):
|
||||
TargetDir = FreeCAD.getUserAppDataDir() + os.path.sep + MaterialDir # $HOME/.FreeCAD
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage("Customed material saving directory is not setup in Fem preference")
|
||||
if not os.path.exists(TargetDir):
|
||||
os.mkdir(TargetDir)
|
||||
|
||||
saveName, Filter = QFileDialog.getSaveFileName(None, "Save a Material property file", TargetDir, "*.FCMat")
|
||||
if not saveName == "":
|
||||
print(saveName)
|
||||
knownMaterials = [self.form.cb_materials.itemText(i) for i in range(self.form.cb_materials.count())]
|
||||
material_name = os.path.basename(saveName[:-len('.FCMat')])
|
||||
if material_name not in knownMaterials:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully save the Material property file: " + saveName + "\n")
|
||||
else:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully overwritren the Material property file: " + saveName + "\n")
|
||||
"""
|
||||
msgBox = QMessageBox()
|
||||
msgBox.setText("FcMat file name {} has existed in {} or system folder, overwriting?\n".format(saveName, TargetDir))
|
||||
msgBox.addButton(QMessageBox.Yes)
|
||||
msgBox.addButton(QMessageBox.No)
|
||||
msgBox.setDefaultButton(QMessageBox.No)
|
||||
ret = msgBox.exec_()
|
||||
if ret == QMessageBox.Yes:
|
||||
self.export_FCMat(saveName, self.obj.Material)
|
||||
FreeCAD.Console.PrintMessage("Successfully overwritren the Material property file: "+ saveName + "\n")
|
||||
"""
|
||||
|
||||
###################geometry reference selection #################
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
if ref[1]:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
else:
|
||||
refname_to_compare_listentry = ref[0].Name
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' --> ', selection[0].Name, ' --> ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
if ref[1]:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
else:
|
||||
item_name = ref[0].Name
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -29,11 +29,16 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemMeshBoundaryLayer:
|
||||
"A View Provider for the FemMeshBoundaryLayer object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -41,6 +46,7 @@ class _ViewProviderFemMeshBoundaryLayer:
|
||||
return ":/icons/fem-femmesh-boundary-layer.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -64,8 +70,7 @@ class _ViewProviderFemMeshBoundaryLayer:
|
||||
if o.isDerivedFrom("Fem::FemMeshObject"):
|
||||
o.ViewObject.hide()
|
||||
# show task panel
|
||||
import PyGui._TaskPanelFemMeshBoundaryLayer
|
||||
taskd = PyGui._TaskPanelFemMeshBoundaryLayer._TaskPanelFemMeshBoundaryLayer(self.Object)
|
||||
taskd = _TaskPanelFemMeshBoundaryLayer(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -87,3 +92,175 @@ class _ViewProviderFemMeshBoundaryLayer:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemMeshBoundaryLayer:
|
||||
'''The TaskPanel for editing References property of FemMeshBoundaryLayer objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces for 3D, Edges for 2D by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshBoundaryLayer.ui")
|
||||
|
||||
QtCore.QObject.connect(self.form.bl_number_of_layers, QtCore.SIGNAL("valueChanged(int)"), self.bl_number_of_layers_changed)
|
||||
QtCore.QObject.connect(self.form.bl_min_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.bl_min_thickness_changed)
|
||||
QtCore.QObject.connect(self.form.bl_growth_rate, QtCore.SIGNAL("valueChanged(double)"), self.bl_growth_rate_changed) # becareful of signal signature for QDoubleSpinbox
|
||||
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_mesh_boundarylayer_props()
|
||||
self.update()
|
||||
|
||||
def get_mesh_boundarylayer_props(self):
|
||||
self.bl_min_thickness = self.obj.MinimumThickness
|
||||
self.bl_number_of_layers = self.obj.NumberOfLayers
|
||||
self.bl_growth_rate = self.obj.GrowthRate
|
||||
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_mesh_boundarylayer_props(self):
|
||||
self.obj.MinimumThickness = self.bl_min_thickness
|
||||
self.obj.NumberOfLayers = self.bl_number_of_layers
|
||||
self.obj.GrowthRate = self.bl_growth_rate
|
||||
self.obj.References = self.references
|
||||
|
||||
def update(self):
|
||||
'fills the widgets with data'
|
||||
self.form.bl_min_thickness.setText(self.bl_min_thickness.UserString)
|
||||
self.form.bl_number_of_layers.setValue(self.bl_number_of_layers)
|
||||
self.form.bl_growth_rate.setValue(self.bl_growth_rate)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def bl_min_thickness_changed(self, base_quantity_value):
|
||||
self.bl_min_thickness = base_quantity_value
|
||||
|
||||
def bl_number_of_layers_changed(self, value):
|
||||
self.bl_number_of_layers = value
|
||||
|
||||
def bl_growth_rate_changed(self, value):
|
||||
self.bl_growth_rate = value
|
||||
|
||||
def accept(self):
|
||||
self.set_mesh_boundarylayer_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
############### identical to FemMeshRegion ############
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
@@ -32,8 +32,18 @@ import FreeCADGui
|
||||
import FemGui
|
||||
|
||||
|
||||
# for the panel
|
||||
import PyObjects._FemMeshGmsh
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
import time
|
||||
|
||||
|
||||
class _ViewProviderFemMeshGmsh:
|
||||
"A View Provider for the FemMeshGmsh object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -52,8 +62,7 @@ class _ViewProviderFemMeshGmsh:
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
self.ViewObject.show() # show the mesh on edit if it is hided
|
||||
import PyGui._TaskPanelFemMeshGmsh
|
||||
taskd = PyGui._TaskPanelFemMeshGmsh._TaskPanelFemMeshGmsh(self.Object)
|
||||
taskd = _TaskPanelFemMeshGmsh(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -139,3 +148,141 @@ class _ViewProviderFemMeshGmsh:
|
||||
except Exception as err:
|
||||
FreeCAD.Console.PrintError("Error in onDelete: " + err.message)
|
||||
return True
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGmsh:
|
||||
'''The TaskPanel for editing References property of FemMeshGmsh objects and creation of new FEM mesh'''
|
||||
|
||||
def __init__(self, obj):
|
||||
self.mesh_obj = obj
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshGmsh.ui")
|
||||
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(100) # 100 milli seconds
|
||||
self.gmsh_runs = False
|
||||
self.console_message_gmsh = ''
|
||||
|
||||
QtCore.QObject.connect(self.form.if_max, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.max_changed)
|
||||
QtCore.QObject.connect(self.form.if_min, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.min_changed)
|
||||
QtCore.QObject.connect(self.form.cb_dimension, QtCore.SIGNAL("activated(int)"), self.choose_dimension)
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.update_timer_text)
|
||||
|
||||
self.form.cb_dimension.addItems(PyObjects._FemMeshGmsh._FemMeshGmsh.known_element_dimensions)
|
||||
|
||||
self.get_mesh_params()
|
||||
self.get_active_analysis()
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel)
|
||||
# show a OK, a apply and a Cancel button
|
||||
# def reject() is called on Cancel button
|
||||
# def clicked(self, button) is needed, to access the apply button
|
||||
|
||||
def accept(self):
|
||||
self.set_mesh_params()
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def clicked(self, button):
|
||||
if button == QtGui.QDialogButtonBox.Apply:
|
||||
self.set_mesh_params()
|
||||
self.run_gmsh()
|
||||
|
||||
def get_mesh_params(self):
|
||||
self.clmax = self.mesh_obj.CharacteristicLengthMax
|
||||
self.clmin = self.mesh_obj.CharacteristicLengthMin
|
||||
self.dimension = self.mesh_obj.ElementDimension
|
||||
|
||||
def set_mesh_params(self):
|
||||
self.mesh_obj.CharacteristicLengthMax = self.clmax
|
||||
self.mesh_obj.CharacteristicLengthMin = self.clmin
|
||||
self.mesh_obj.ElementDimension = self.dimension
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_max.setText(self.clmax.UserString)
|
||||
self.form.if_min.setText(self.clmin.UserString)
|
||||
index_dimension = self.form.cb_dimension.findText(self.dimension)
|
||||
self.form.cb_dimension.setCurrentIndex(index_dimension)
|
||||
|
||||
def console_log(self, message="", color="#000000"):
|
||||
self.console_message_gmsh = self.console_message_gmsh + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.te_output.setText(self.console_message_gmsh)
|
||||
self.form.te_output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def update_timer_text(self):
|
||||
# print('timer1')
|
||||
if self.gmsh_runs:
|
||||
print('timer2')
|
||||
# print('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def max_changed(self, base_quantity_value):
|
||||
self.clmax = base_quantity_value
|
||||
|
||||
def min_changed(self, base_quantity_value):
|
||||
self.clmin = base_quantity_value
|
||||
|
||||
def choose_dimension(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
self.form.cb_dimension.setCurrentIndex(index)
|
||||
self.dimension = str(self.form.cb_dimension.itemText(index)) # form returns unicode
|
||||
|
||||
def run_gmsh(self):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
part = self.obj.Part
|
||||
if self.mesh_obj.MeshRegionList:
|
||||
if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"): # other part obj might not have a Proxy, thus an exception would be raised
|
||||
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."
|
||||
QtGui.QMessageBox.critical(None, "Shape to mesh is a BooleanFragmentsCompound and mesh regions are defined", error_message)
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.console_message_gmsh = ''
|
||||
self.gmsh_runs = True
|
||||
self.console_log("We are going to start ...")
|
||||
self.get_active_analysis()
|
||||
import femmesh.gmshtools as gmshtools
|
||||
gmsh_mesh = gmshtools.GmshTools(self.obj, self.analysis)
|
||||
self.console_log("Start Gmsh ...")
|
||||
error = ''
|
||||
try:
|
||||
error = gmsh_mesh.create_mesh()
|
||||
except:
|
||||
import sys
|
||||
print("Unexpected error when creating mesh: ", sys.exc_info()[0])
|
||||
if error:
|
||||
print(error)
|
||||
self.console_log('Gmsh had warnings ...')
|
||||
self.console_log(error, '#FF0000')
|
||||
else:
|
||||
self.console_log('Clean run of Gmsh')
|
||||
self.console_log("Gmsh done!")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
self.Timer.stop()
|
||||
self.update()
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def get_active_analysis(self):
|
||||
import FemGui
|
||||
self.analysis = FemGui.getActiveAnalysis()
|
||||
if self.analysis:
|
||||
for m in FemGui.getActiveAnalysis().Group:
|
||||
if m.Name == self.mesh_obj.Name:
|
||||
print('Active analysis found: ' + self.analysis.Name)
|
||||
return
|
||||
else:
|
||||
# print('Mesh is not member of active analysis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
else:
|
||||
# print('No active analyis, means no group meshing')
|
||||
self.analysis = None # no group meshing
|
||||
|
||||
@@ -29,7 +29,11 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemMeshGroup:
|
||||
@@ -41,6 +45,7 @@ class _ViewProviderFemMeshGroup:
|
||||
return ":/icons/fem-femmesh-from-shape.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -64,8 +69,7 @@ class _ViewProviderFemMeshGroup:
|
||||
if o.isDerivedFrom("Fem::FemMeshObject"):
|
||||
o.ViewObject.hide()
|
||||
# show task panel
|
||||
import PyGui._TaskPanelFemMeshGroup
|
||||
taskd = PyGui._TaskPanelFemMeshGroup._TaskPanelFemMeshGroup(self.Object)
|
||||
taskd = _TaskPanelFemMeshGroup(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -87,3 +91,195 @@ class _ViewProviderFemMeshGroup:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemMeshGroup:
|
||||
'''The TaskPanel for editing References property of FemMeshGroup objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshGroup.ui")
|
||||
QtCore.QObject.connect(self.form.rb_name, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_name)
|
||||
QtCore.QObject.connect(self.form.rb_label, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_label)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_meshgroup_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_meshgroup_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_meshgroup_props(self):
|
||||
self.use_label = self.obj.UseLabel
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_meshgroup_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.UseLabel = self.use_label
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.rb_name.setChecked(not self.use_label)
|
||||
self.form.rb_label.setChecked(self.use_label)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def choose_exportidentifier_name(self, state):
|
||||
self.use_label = not state
|
||||
|
||||
def choose_exportidentifier_label(self, state):
|
||||
self.use_label = state
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -29,11 +29,16 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
from pivy import coin
|
||||
|
||||
|
||||
# for the panel
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
|
||||
|
||||
class _ViewProviderFemMeshRegion:
|
||||
"A View Provider for the FemMeshRegion object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -41,6 +46,7 @@ class _ViewProviderFemMeshRegion:
|
||||
return ":/icons/fem-femmesh-region.svg"
|
||||
|
||||
def attach(self, vobj):
|
||||
from pivy import coin
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
self.standard = coin.SoGroup()
|
||||
@@ -64,8 +70,7 @@ class _ViewProviderFemMeshRegion:
|
||||
if o.isDerivedFrom("Fem::FemMeshObject"):
|
||||
o.ViewObject.hide()
|
||||
# show task panel
|
||||
import PyGui._TaskPanelFemMeshRegion
|
||||
taskd = PyGui._TaskPanelFemMeshRegion._TaskPanelFemMeshRegion(self.Object)
|
||||
taskd = _TaskPanelFemMeshRegion(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
@@ -87,3 +92,190 @@ class _ViewProviderFemMeshRegion:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemMeshRegion:
|
||||
'''The TaskPanel for editing References property of FemMeshRegion objects'''
|
||||
|
||||
def __init__(self, obj):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
self.sel_server = None
|
||||
self.obj = obj
|
||||
self.selection_mode_solid = False
|
||||
self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
|
||||
self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
|
||||
self.obj_notvisible = []
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemMeshRegion.ui")
|
||||
QtCore.QObject.connect(self.form.if_elelen, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.elelen_changed)
|
||||
QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
|
||||
QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
|
||||
QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
|
||||
self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape)
|
||||
self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
|
||||
|
||||
self.get_meshregion_props()
|
||||
self.update()
|
||||
|
||||
def accept(self):
|
||||
self.setback_listobj_visibility()
|
||||
self.set_meshregion_props()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
return True
|
||||
|
||||
def get_meshregion_props(self):
|
||||
self.elelen = self.obj.CharacteristicLength
|
||||
self.references = []
|
||||
if self.obj.References:
|
||||
self.tuplereferences = self.obj.References
|
||||
self.get_references()
|
||||
|
||||
def set_meshregion_props(self):
|
||||
self.obj.References = self.references
|
||||
self.obj.CharacteristicLength = self.elelen
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.if_elelen.setText(self.elelen.UserString)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def elelen_changed(self, base_quantity_value):
|
||||
self.elelen = base_quantity_value
|
||||
|
||||
def choose_selection_mode_standard(self, state):
|
||||
self.selection_mode_solid = not state
|
||||
if self.sel_server and not self.selection_mode_solid:
|
||||
print(self.selection_mode_std_print_message)
|
||||
|
||||
def choose_selection_mode_solid(self, state):
|
||||
self.selection_mode_solid = state
|
||||
if self.sel_server and self.selection_mode_solid:
|
||||
print(self.selection_mode_solid_print_message)
|
||||
|
||||
def get_references(self):
|
||||
for ref in self.tuplereferences:
|
||||
for elem in ref[1]:
|
||||
self.references.append((ref[0], elem))
|
||||
|
||||
def references_list_right_clicked(self, QPos):
|
||||
self.form.contextMenu = QtGui.QMenu()
|
||||
menu_item = self.form.contextMenu.addAction("Remove Reference")
|
||||
if not self.references:
|
||||
menu_item.setDisabled(True)
|
||||
self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
|
||||
parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
|
||||
self.form.contextMenu.move(parentPosition + QPos)
|
||||
self.form.contextMenu.show()
|
||||
|
||||
def remove_reference(self):
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
self.references.remove(ref)
|
||||
self.rebuild_list_References()
|
||||
|
||||
def add_references(self):
|
||||
'''Called if Button add_reference is triggered'''
|
||||
# in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
|
||||
# here the addReference button EditTaskPanel has to be triggered to start selection mode
|
||||
self.setback_listobj_visibility()
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
# start SelectionObserver and parse the function to add the References to the widget
|
||||
if self.selection_mode_solid: # print message on button click
|
||||
print_message = self.selection_mode_solid_print_message
|
||||
else:
|
||||
print_message = self.selection_mode_std_print_message
|
||||
if not self.sel_server:
|
||||
# if we do not check, we would start a new SelectionObserver on every click on addReference button
|
||||
# but close only one SelectionObserver on leaving the task panel
|
||||
from . import FemSelectionObserver
|
||||
self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
|
||||
|
||||
def selectionParser(self, selection):
|
||||
print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
if hasattr(selection[0], "Shape") and selection[1]:
|
||||
elt = selection[0].Shape.getElement(selection[1])
|
||||
if self.selection_mode_solid:
|
||||
# in solid selection mode use edges and faces for selection of a solid
|
||||
solid_to_add = None
|
||||
if elt.ShapeType == 'Edge':
|
||||
found_edge = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Edges:
|
||||
if elt.isSame(e):
|
||||
if not found_edge:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
elif elt.ShapeType == 'Face':
|
||||
found_face = False
|
||||
for i, s in enumerate(selection[0].Shape.Solids):
|
||||
for e in s.Faces:
|
||||
if elt.isSame(e):
|
||||
if not found_face:
|
||||
solid_to_add = str(i + 1)
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
|
||||
solid_to_add = None
|
||||
found_edge = True
|
||||
if solid_to_add:
|
||||
selection = (selection[0], 'Solid' + solid_to_add)
|
||||
print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
|
||||
else:
|
||||
return
|
||||
if selection not in self.references:
|
||||
self.references.append(selection)
|
||||
self.rebuild_list_References()
|
||||
else:
|
||||
FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
|
||||
|
||||
def rebuild_list_References(self):
|
||||
self.form.list_References.clear()
|
||||
items = []
|
||||
for ref in self.references:
|
||||
item_name = ref[0].Name + ':' + ref[1]
|
||||
items.append(item_name)
|
||||
for listItemName in sorted(items):
|
||||
self.form.list_References.addItem(listItemName)
|
||||
|
||||
def select_clicked_reference_shape(self):
|
||||
self.setback_listobj_visibility()
|
||||
if self.sel_server:
|
||||
FreeCADGui.Selection.removeObserver(self.sel_server)
|
||||
self.sel_server = None
|
||||
if not self.sel_server:
|
||||
if not self.references:
|
||||
return
|
||||
currentItemName = str(self.form.list_References.currentItem().text())
|
||||
for ref in self.references:
|
||||
refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
|
||||
if refname_to_compare_listentry == currentItemName:
|
||||
# print( 'found: shape: ' + ref[0].Name + ' element: ' + ref[1])
|
||||
if not ref[0].ViewObject.Visibility:
|
||||
self.obj_notvisible.append(ref[0])
|
||||
ref[0].ViewObject.Visibility = True
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.Selection.addSelection(ref[0], ref[1])
|
||||
|
||||
def setback_listobj_visibility(self):
|
||||
'''set back Visibility of the list objects
|
||||
'''
|
||||
for obj in self.obj_notvisible:
|
||||
obj.ViewObject.Visibility = False
|
||||
self.obj_notvisible = []
|
||||
|
||||
@@ -30,12 +30,20 @@ __url__ = "http://www.freecadweb.org"
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
|
||||
# for the panel
|
||||
import FemGui
|
||||
import femresult.resulttools as resulttools
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
import numpy as np
|
||||
|
||||
|
||||
class _ViewProviderFemResultMechanical:
|
||||
"""A View Provider for the FemResultObject Python dervied FemResult class
|
||||
"""
|
||||
"A View Provider for the FemResultObject Python dervied FemResult class"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
@@ -69,14 +77,14 @@ class _ViewProviderFemResultMechanical:
|
||||
hide_femmeshes_postpiplines()
|
||||
# only show the FEM result mesh
|
||||
self.Object.Mesh.ViewObject.show()
|
||||
import PyGui._TaskPanelFemResultShow
|
||||
taskd = PyGui._TaskPanelFemResultShow._TaskPanelFemResultShow(self.Object)
|
||||
taskd = _TaskPanelFemResultShow(self.Object)
|
||||
taskd.obj = vobj.Object
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
else:
|
||||
error_message = 'FEM: Result object has no appropriate FEM mesh.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
from PySide import QtGui
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
return False
|
||||
|
||||
@@ -103,9 +111,392 @@ class _ViewProviderFemResultMechanical:
|
||||
return True
|
||||
|
||||
|
||||
class _TaskPanelFemResultShow:
|
||||
'''The task panel for the post-processing'''
|
||||
|
||||
def __init__(self, obj):
|
||||
self.result_obj = obj
|
||||
self.mesh_obj = self.result_obj.Mesh
|
||||
# task panel should be started by use of setEdit of view provider
|
||||
# in view provider checks: Mesh, active analysis and if Mesh and result are in active analysis
|
||||
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemResultShow.ui")
|
||||
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
self.restore_result_settings_in_dialog = self.fem_prefs.GetBool("RestoreResultDialog", True)
|
||||
|
||||
# Connect Signals and Slots
|
||||
# result type radio buttons
|
||||
QtCore.QObject.connect(self.form.rb_none, QtCore.SIGNAL("toggled(bool)"), self.none_selected)
|
||||
QtCore.QObject.connect(self.form.rb_abs_displacement, QtCore.SIGNAL("toggled(bool)"), self.abs_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_x_displacement, QtCore.SIGNAL("toggled(bool)"), self.x_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_y_displacement, QtCore.SIGNAL("toggled(bool)"), self.y_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_z_displacement, QtCore.SIGNAL("toggled(bool)"), self.z_displacement_selected)
|
||||
QtCore.QObject.connect(self.form.rb_temperature, QtCore.SIGNAL("toggled(bool)"), self.temperature_selected)
|
||||
QtCore.QObject.connect(self.form.rb_vm_stress, QtCore.SIGNAL("toggled(bool)"), self.vm_stress_selected)
|
||||
QtCore.QObject.connect(self.form.rb_maxprin, QtCore.SIGNAL("toggled(bool)"), self.max_prin_selected)
|
||||
QtCore.QObject.connect(self.form.rb_minprin, QtCore.SIGNAL("toggled(bool)"), self.min_prin_selected)
|
||||
QtCore.QObject.connect(self.form.rb_max_shear_stress, QtCore.SIGNAL("toggled(bool)"), self.max_shear_selected)
|
||||
QtCore.QObject.connect(self.form.rb_massflowrate, QtCore.SIGNAL("toggled(bool)"), self.massflowrate_selected)
|
||||
QtCore.QObject.connect(self.form.rb_networkpressure, QtCore.SIGNAL("toggled(bool)"), self.networkpressure_selected)
|
||||
QtCore.QObject.connect(self.form.rb_peeq, QtCore.SIGNAL("toggled(bool)"), self.peeq_selected)
|
||||
|
||||
# displacement
|
||||
QtCore.QObject.connect(self.form.cb_show_displacement, QtCore.SIGNAL("clicked(bool)"), self.show_displacement)
|
||||
QtCore.QObject.connect(self.form.hsb_displacement_factor, QtCore.SIGNAL("valueChanged(int)"), self.hsb_disp_factor_changed)
|
||||
QtCore.QObject.connect(self.form.sb_displacement_factor, QtCore.SIGNAL("valueChanged(int)"), self.sb_disp_factor_changed)
|
||||
QtCore.QObject.connect(self.form.sb_displacement_factor_max, QtCore.SIGNAL("valueChanged(int)"), self.sb_disp_factor_max_changed)
|
||||
|
||||
# user defined equation
|
||||
QtCore.QObject.connect(self.form.user_def_eq, QtCore.SIGNAL("textchanged()"), self.user_defined_text)
|
||||
QtCore.QObject.connect(self.form.calculate, QtCore.SIGNAL("clicked()"), self.calculate)
|
||||
|
||||
self.update()
|
||||
if self.restore_result_settings_in_dialog:
|
||||
self.restore_result_dialog()
|
||||
else:
|
||||
self.restore_initial_result_dialog()
|
||||
|
||||
def restore_result_dialog(self):
|
||||
try:
|
||||
rt = FreeCAD.FEM_dialog["results_type"]
|
||||
if rt == "None":
|
||||
self.form.rb_none.setChecked(True)
|
||||
self.none_selected(True)
|
||||
elif rt == "Uabs":
|
||||
self.form.rb_abs_displacement.setChecked(True)
|
||||
self.abs_displacement_selected(True)
|
||||
elif rt == "U1":
|
||||
self.form.rb_x_displacement.setChecked(True)
|
||||
self.x_displacement_selected(True)
|
||||
elif rt == "U2":
|
||||
self.form.rb_y_displacement.setChecked(True)
|
||||
self.y_displacement_selected(True)
|
||||
elif rt == "U3":
|
||||
self.form.rb_z_displacement.setChecked(True)
|
||||
self.z_displacement_selected(True)
|
||||
elif rt == "Temp":
|
||||
self.form.rb_temperature.setChecked(True)
|
||||
self.temperature_selected(True)
|
||||
elif rt == "Sabs":
|
||||
self.form.rb_vm_stress.setChecked(True)
|
||||
self.vm_stress_selected(True)
|
||||
elif rt == "MaxPrin":
|
||||
self.form.rb_maxprin.setChecked(True)
|
||||
self.max_prin_selected(True)
|
||||
elif rt == "MinPrin":
|
||||
self.form.rb_minprin.setChecked(True)
|
||||
self.min_prin_selected(True)
|
||||
elif rt == "MaxShear":
|
||||
self.form.rb_max_shear_stress.setChecked(True)
|
||||
self.max_shear_selected(True)
|
||||
elif rt == "MFlow":
|
||||
self.form.rb_massflowrate.setChecked(True)
|
||||
self.massflowrate_selected(True)
|
||||
elif rt == "NPress":
|
||||
self.form.rb_networkpressure.setChecked(True)
|
||||
self.networkpressure_selected(True)
|
||||
elif rt == "Peeq":
|
||||
self.form.rb_peeq.setChecked(True)
|
||||
self.peeq_selected(True)
|
||||
|
||||
sd = FreeCAD.FEM_dialog["show_disp"]
|
||||
self.form.cb_show_displacement.setChecked(sd)
|
||||
self.show_displacement(sd)
|
||||
|
||||
df = FreeCAD.FEM_dialog["disp_factor"]
|
||||
dfm = FreeCAD.FEM_dialog["disp_factor_max"]
|
||||
self.form.hsb_displacement_factor.setMaximum(dfm)
|
||||
self.form.hsb_displacement_factor.setValue(df)
|
||||
self.form.sb_displacement_factor_max.setValue(dfm)
|
||||
self.form.sb_displacement_factor.setValue(df)
|
||||
except:
|
||||
self.restore_initial_result_dialog()
|
||||
|
||||
def restore_initial_result_dialog(self):
|
||||
FreeCAD.FEM_dialog = {"results_type": "None", "show_disp": False,
|
||||
"disp_factor": 0, "disp_factor_max": 100}
|
||||
self.reset_mesh_deformation()
|
||||
self.reset_mesh_color()
|
||||
|
||||
def getStandardButtons(self):
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def get_result_stats(self, type_name):
|
||||
return resulttools.get_stats(self.result_obj, type_name)
|
||||
|
||||
def none_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "None"
|
||||
self.set_result_stats("mm", 0.0, 0.0, 0.0)
|
||||
self.reset_mesh_color()
|
||||
|
||||
def abs_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Uabs"
|
||||
self.select_displacement_type("Uabs")
|
||||
|
||||
def x_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U1"
|
||||
self.select_displacement_type("U1")
|
||||
|
||||
def y_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U2"
|
||||
self.select_displacement_type("U2")
|
||||
|
||||
def z_displacement_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "U3"
|
||||
self.select_displacement_type("U3")
|
||||
|
||||
def vm_stress_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Sabs"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.StressValues)
|
||||
(minm, avg, maxm) = self.get_result_stats("Sabs")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def max_shear_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MaxShear"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.MaxShear)
|
||||
(minm, avg, maxm) = self.get_result_stats("MaxShear")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def max_prin_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MaxPrin"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.PrincipalMax)
|
||||
(minm, avg, maxm) = self.get_result_stats("MaxPrin")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def temperature_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Temp"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.Temperature)
|
||||
(minm, avg, maxm) = self.get_result_stats("Temp")
|
||||
self.set_result_stats("K", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def massflowrate_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MFlow"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.MassFlowRate)
|
||||
(minm, avg, maxm) = self.get_result_stats("MFlow")
|
||||
self.set_result_stats("kg/s", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def networkpressure_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "NPress"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.NetworkPressure)
|
||||
(minm, avg, maxm) = self.get_result_stats("NPress")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def min_prin_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "MinPrin"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.PrincipalMin)
|
||||
(minm, avg, maxm) = self.get_result_stats("MinPrin")
|
||||
self.set_result_stats("MPa", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def peeq_selected(self, state):
|
||||
FreeCAD.FEM_dialog["results_type"] = "Peeq"
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.Peeq)
|
||||
(minm, avg, maxm) = self.get_result_stats("Peeq")
|
||||
self.set_result_stats("", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def user_defined_text(self, equation):
|
||||
FreeCAD.FEM_dialog["results_type"] = "user"
|
||||
self.form.user_def_eq.toPlainText()
|
||||
|
||||
def calculate(self):
|
||||
FreeCAD.FEM_dialog["results_type"] = "None"
|
||||
self.update()
|
||||
self.restore_result_dialog()
|
||||
# Convert existing values to numpy array
|
||||
P1 = np.array(self.result_obj.PrincipalMax)
|
||||
P2 = np.array(self.result_obj.PrincipalMed)
|
||||
P3 = np.array(self.result_obj.PrincipalMin)
|
||||
Von = np.array(self.result_obj.StressValues)
|
||||
Peeq = np.array(self.result_obj.Peeq)
|
||||
T = np.array(self.result_obj.Temperature)
|
||||
MF = np.array(self.result_obj.MassFlowRate)
|
||||
NP = np.array(self.result_obj.NetworkPressure)
|
||||
dispvectors = np.array(self.result_obj.DisplacementVectors)
|
||||
x = np.array(dispvectors[:, 0])
|
||||
y = np.array(dispvectors[:, 1])
|
||||
z = np.array(dispvectors[:, 2])
|
||||
stressvectors = np.array(self.result_obj.StressVectors)
|
||||
sx = np.array(stressvectors[:, 0])
|
||||
sy = np.array(stressvectors[:, 1])
|
||||
sz = np.array(stressvectors[:, 2])
|
||||
strainvectors = np.array(self.result_obj.StrainVectors)
|
||||
ex = np.array(strainvectors[:, 0])
|
||||
ey = np.array(strainvectors[:, 1])
|
||||
ez = np.array(strainvectors[:, 2])
|
||||
userdefined_eq = self.form.user_def_eq.toPlainText() # Get equation to be used
|
||||
UserDefinedFormula = eval(userdefined_eq).tolist()
|
||||
self.result_obj.UserDefined = UserDefinedFormula
|
||||
minm = min(UserDefinedFormula)
|
||||
avg = sum(UserDefinedFormula) / len(UserDefinedFormula)
|
||||
maxm = max(UserDefinedFormula)
|
||||
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, UserDefinedFormula)
|
||||
self.set_result_stats("", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
del x, y, z, T, Von, Peeq, P1, P2, P3, sx, sy, sz, ex, ey, ez, MF, NP # Dummy use to get around flake8, varibles not being used
|
||||
|
||||
def select_displacement_type(self, disp_type):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
if disp_type == "Uabs":
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, self.result_obj.DisplacementLengths)
|
||||
else:
|
||||
match = {"U1": 0, "U2": 1, "U3": 2}
|
||||
d = zip(*self.result_obj.DisplacementVectors)
|
||||
displacements = list(d[match[disp_type]])
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(self.result_obj.NodeNumbers, displacements)
|
||||
(minm, avg, maxm) = self.get_result_stats(disp_type)
|
||||
self.set_result_stats("mm", minm, avg, maxm)
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def set_result_stats(self, unit, minm, avg, maxm):
|
||||
self.form.le_min.setProperty("unit", unit)
|
||||
self.form.le_min.setText("{:.6} {}".format(minm, unit))
|
||||
self.form.le_avg.setProperty("unit", unit)
|
||||
self.form.le_avg.setText("{:.6} {}".format(avg, unit))
|
||||
self.form.le_max.setProperty("unit", unit)
|
||||
self.form.le_max.setText("{:.6} {}".format(maxm, unit))
|
||||
|
||||
def update_displacement(self, factor=None):
|
||||
if factor is None:
|
||||
if FreeCAD.FEM_dialog["show_disp"]:
|
||||
factor = self.form.hsb_displacement_factor.value()
|
||||
else:
|
||||
factor = 0.0
|
||||
self.mesh_obj.ViewObject.applyDisplacement(factor)
|
||||
|
||||
def show_displacement(self, checked):
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
FreeCAD.FEM_dialog["show_disp"] = checked
|
||||
if "result_obj" in FreeCAD.FEM_dialog:
|
||||
if FreeCAD.FEM_dialog["result_obj"] != self.result_obj:
|
||||
self.update_displacement()
|
||||
FreeCAD.FEM_dialog["result_obj"] = self.result_obj
|
||||
if self.suitable_results:
|
||||
self.mesh_obj.ViewObject.setNodeDisplacementByVectors(self.result_obj.NodeNumbers, self.result_obj.DisplacementVectors)
|
||||
self.update_displacement()
|
||||
QtGui.qApp.restoreOverrideCursor()
|
||||
|
||||
def hsb_disp_factor_changed(self, value):
|
||||
self.form.sb_displacement_factor.setValue(value)
|
||||
self.update_displacement()
|
||||
|
||||
def sb_disp_factor_max_changed(self, value):
|
||||
FreeCAD.FEM_dialog["disp_factor_max"] = value
|
||||
self.form.hsb_displacement_factor.setMaximum(value)
|
||||
|
||||
def sb_disp_factor_changed(self, value):
|
||||
FreeCAD.FEM_dialog["disp_factor"] = value
|
||||
self.form.hsb_displacement_factor.setValue(value)
|
||||
|
||||
def disable_empty_result_buttons(self):
|
||||
''' disable radio buttons if result does not exists in result object'''
|
||||
'''assignments
|
||||
DisplacementLengths --> rb_abs_displacement
|
||||
DisplacementVectors --> rb_x_displacement, rb_y_displacement, rb_z_displacement
|
||||
Temperature --> rb_temperature
|
||||
StressValues --> rb_vm_stress
|
||||
PrincipalMax --> rb_maxprin
|
||||
PrincipalMin --> rb_minprin
|
||||
MaxShear --> rb_max_shear_stress
|
||||
MassFlowRate --> rb_massflowrate
|
||||
NetworkPressure --> rb_networkpressure
|
||||
Peeq --> rb_peeq'''
|
||||
if len(self.result_obj.DisplacementLengths) == 0:
|
||||
self.form.rb_abs_displacement.setEnabled(0)
|
||||
if len(self.result_obj.DisplacementVectors) == 0:
|
||||
self.form.rb_x_displacement.setEnabled(0)
|
||||
self.form.rb_y_displacement.setEnabled(0)
|
||||
self.form.rb_z_displacement.setEnabled(0)
|
||||
if len(self.result_obj.Temperature) == 0:
|
||||
self.form.rb_temperature.setEnabled(0)
|
||||
if len(self.result_obj.StressValues) == 0:
|
||||
self.form.rb_vm_stress.setEnabled(0)
|
||||
if len(self.result_obj.PrincipalMax) == 0:
|
||||
self.form.rb_maxprin.setEnabled(0)
|
||||
if len(self.result_obj.PrincipalMin) == 0:
|
||||
self.form.rb_minprin.setEnabled(0)
|
||||
if len(self.result_obj.MaxShear) == 0:
|
||||
self.form.rb_max_shear_stress.setEnabled(0)
|
||||
if len(self.result_obj.MassFlowRate) == 0:
|
||||
self.form.rb_massflowrate.setEnabled(0)
|
||||
if len(self.result_obj.NetworkPressure) == 0:
|
||||
self.form.rb_networkpressure.setEnabled(0)
|
||||
if len(self.result_obj.Peeq) == 0:
|
||||
self.form.rb_peeq.setEnabled(0)
|
||||
|
||||
def update(self):
|
||||
self.suitable_results = False
|
||||
self.disable_empty_result_buttons()
|
||||
if (self.mesh_obj.FemMesh.NodeCount == len(self.result_obj.NodeNumbers)):
|
||||
self.suitable_results = True
|
||||
hide_parts_constraints()
|
||||
else:
|
||||
if not self.mesh_obj.FemMesh.VolumeCount:
|
||||
error_message = 'FEM: Graphical bending stress output for beam or shell FEM Meshes not yet supported.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
else:
|
||||
error_message = 'FEM: Result node numbers are not equal to FEM Mesh NodeCount.\n'
|
||||
FreeCAD.Console.PrintError(error_message)
|
||||
QtGui.QMessageBox.critical(None, 'No result object', error_message)
|
||||
|
||||
def reset_mesh_deformation(self):
|
||||
self.mesh_obj.ViewObject.applyDisplacement(0.0)
|
||||
|
||||
def reset_mesh_color(self):
|
||||
self.mesh_obj.ViewObject.NodeColor = {}
|
||||
self.mesh_obj.ViewObject.ElementColor = {}
|
||||
node_numbers = self.mesh_obj.FemMesh.Nodes.keys()
|
||||
zero_values = [0] * len(node_numbers)
|
||||
self.mesh_obj.ViewObject.setNodeColorByScalars(node_numbers, zero_values)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.Control.closeDialog() # if the taks panell is called from Command obj is not in edit mode thus reset edit does not cleses the dialog, may be do not call but set in edit instead
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
|
||||
# helper
|
||||
def hide_femmeshes_postpiplines():
|
||||
# hide all visible FEM mesh objects and VTK FemPostPipeline objects
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if o.isDerivedFrom("Fem::FemMeshObject") or o.isDerivedFrom("Fem::FemPostPipeline"):
|
||||
o.ViewObject.hide()
|
||||
|
||||
|
||||
def hide_parts_constraints():
|
||||
fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
|
||||
hide_constraints = fem_prefs.GetBool("HideConstraint", False)
|
||||
if hide_constraints:
|
||||
for o in FreeCAD.ActiveDocument.Objects:
|
||||
if o.isDerivedFrom('Fem::FemAnalysis'):
|
||||
for acnstrmesh in FemGui.getActiveAnalysis().Group:
|
||||
if "Constraint" in acnstrmesh.TypeId:
|
||||
acnstrmesh.ViewObject.Visibility = False
|
||||
break
|
||||
|
||||
@@ -32,8 +32,22 @@ import FreeCADGui
|
||||
import FemGui
|
||||
|
||||
|
||||
# for the panel
|
||||
import FemToolsCcx
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide.QtCore import Qt
|
||||
from PySide.QtGui import QApplication
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
if sys.version_info.major >= 3:
|
||||
unicode = str
|
||||
|
||||
|
||||
class _ViewProviderFemSolverCalculix:
|
||||
"A View Provider for the FemSolverCalculix object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
@@ -51,8 +65,7 @@ class _ViewProviderFemSolverCalculix:
|
||||
return
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
import PyGui._TaskPanelFemSolverCalculix
|
||||
taskd = PyGui._TaskPanelFemSolverCalculix._TaskPanelFemSolverCalculix(self.Object)
|
||||
taskd = _TaskPanelFemSolverCalculix(self.Object)
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
return True
|
||||
|
||||
@@ -83,3 +96,255 @@ class _ViewProviderFemSolverCalculix:
|
||||
|
||||
def __setstate__(self, state):
|
||||
return None
|
||||
|
||||
|
||||
class _TaskPanelFemSolverCalculix:
|
||||
'''The TaskPanel for CalculiX ccx tools solver object'''
|
||||
|
||||
def __init__(self, solver_object):
|
||||
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/PyGui/TaskPanelFemSolverCalculix.ui")
|
||||
self.ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx")
|
||||
ccx_binary = self.ccx_prefs.GetString("ccxBinaryPath", "")
|
||||
if ccx_binary:
|
||||
self.CalculixBinary = ccx_binary
|
||||
print ("Using CalculiX binary path from FEM preferences: {}".format(ccx_binary))
|
||||
else:
|
||||
from platform import system
|
||||
if system() == 'Linux':
|
||||
self.CalculixBinary = 'ccx'
|
||||
elif system() == 'Windows':
|
||||
self.CalculixBinary = FreeCAD.getHomePath() + 'bin/ccx.exe'
|
||||
else:
|
||||
self.CalculixBinary = 'ccx'
|
||||
|
||||
self.solver_object = solver_object
|
||||
|
||||
self.Calculix = QtCore.QProcess()
|
||||
self.Timer = QtCore.QTimer()
|
||||
self.Timer.start(300)
|
||||
|
||||
self.fem_console_message = ''
|
||||
|
||||
# Connect Signals and Slots
|
||||
QtCore.QObject.connect(self.form.tb_choose_working_dir, QtCore.SIGNAL("clicked()"), self.choose_working_dir)
|
||||
QtCore.QObject.connect(self.form.pb_write_inp, QtCore.SIGNAL("clicked()"), self.write_input_file_handler)
|
||||
QtCore.QObject.connect(self.form.pb_edit_inp, QtCore.SIGNAL("clicked()"), self.editCalculixInputFile)
|
||||
QtCore.QObject.connect(self.form.pb_run_ccx, QtCore.SIGNAL("clicked()"), self.runCalculix)
|
||||
QtCore.QObject.connect(self.form.rb_static_analysis, QtCore.SIGNAL("clicked()"), self.select_static_analysis)
|
||||
QtCore.QObject.connect(self.form.rb_frequency_analysis, QtCore.SIGNAL("clicked()"), self.select_frequency_analysis)
|
||||
QtCore.QObject.connect(self.form.rb_thermomech_analysis, QtCore.SIGNAL("clicked()"), self.select_thermomech_analysis)
|
||||
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("started()"), self.calculixStarted)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("stateChanged(QProcess::ProcessState)"), self.calculixStateChanged)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("error(QProcess::ProcessError)"), self.calculixError)
|
||||
QtCore.QObject.connect(self.Calculix, QtCore.SIGNAL("finished(int)"), self.calculixFinished)
|
||||
|
||||
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.UpdateText)
|
||||
|
||||
self.update()
|
||||
|
||||
def getStandardButtons(self):
|
||||
# only show a close button
|
||||
# def accept() in no longer needed, since there is no OK button
|
||||
return int(QtGui.QDialogButtonBox.Close)
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.ActiveDocument.resetEdit()
|
||||
|
||||
def update(self):
|
||||
'fills the widgets'
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
if self.solver_object.AnalysisType == 'static':
|
||||
self.form.rb_static_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'frequency':
|
||||
self.form.rb_frequency_analysis.setChecked(True)
|
||||
elif self.solver_object.AnalysisType == 'thermomech':
|
||||
self.form.rb_thermomech_analysis.setChecked(True)
|
||||
return
|
||||
|
||||
def femConsoleMessage(self, message="", color="#000000"):
|
||||
self.fem_console_message = self.fem_console_message + '<font color="#0000FF">{0:4.1f}:</font> <font color="{1}">{2}</font><br>'.\
|
||||
format(time.time() - self.Start, color, message.encode('utf-8', 'replace'))
|
||||
self.form.textEdit_Output.setText(self.fem_console_message)
|
||||
self.form.textEdit_Output.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
def printCalculiXstdout(self):
|
||||
out = self.Calculix.readAllStandardOutput()
|
||||
if out.isEmpty():
|
||||
self.femConsoleMessage("CalculiX stdout is empty", "#FF0000")
|
||||
else:
|
||||
try:
|
||||
out = unicode(out, 'utf-8', 'replace')
|
||||
rx = QtCore.QRegExp("\\*ERROR.*\\n\\n")
|
||||
rx.setMinimal(True)
|
||||
pos = rx.indexIn(out)
|
||||
while not pos < 0:
|
||||
match = rx.cap(0)
|
||||
FreeCAD.Console.PrintError(match.strip().replace('\n', ' ') + '\n')
|
||||
pos = rx.indexIn(out, pos + 1)
|
||||
out = os.linesep.join([s for s in out.splitlines() if s])
|
||||
self.femConsoleMessage(out.replace('\n', '<br>'))
|
||||
except UnicodeDecodeError:
|
||||
self.femConsoleMessage("Error converting stdout from CalculiX", "#FF0000")
|
||||
|
||||
def UpdateText(self):
|
||||
if(self.Calculix.state() == QtCore.QProcess.ProcessState.Running):
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def calculixError(self, error):
|
||||
print ("Error() {}".format(error))
|
||||
self.femConsoleMessage("CalculiX execute error: {}".format(error), "#FF0000")
|
||||
|
||||
def calculixStarted(self):
|
||||
print ("calculixStarted()")
|
||||
print (self.Calculix.state())
|
||||
self.form.pb_run_ccx.setText("Break CalculiX")
|
||||
|
||||
def calculixStateChanged(self, newState):
|
||||
if (newState == QtCore.QProcess.ProcessState.Starting):
|
||||
self.femConsoleMessage("Starting CalculiX...")
|
||||
if (newState == QtCore.QProcess.ProcessState.Running):
|
||||
self.femConsoleMessage("CalculiX is running...")
|
||||
if (newState == QtCore.QProcess.ProcessState.NotRunning):
|
||||
self.femConsoleMessage("CalculiX stopped.")
|
||||
|
||||
def calculixFinished(self, exitCode):
|
||||
print ("calculixFinished() {}".format(exitCode))
|
||||
print (self.Calculix.state())
|
||||
|
||||
# Restore previous cwd
|
||||
QtCore.QDir.setCurrent(self.cwd)
|
||||
|
||||
self.printCalculiXstdout()
|
||||
self.Timer.stop()
|
||||
|
||||
self.femConsoleMessage("CalculiX done!", "#00AA00")
|
||||
|
||||
self.form.pb_run_ccx.setText("Re-run CalculiX")
|
||||
self.femConsoleMessage("Loading result sets...")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.reset_mesh_purge_results_checked()
|
||||
fea.inp_file_name = self.inp_file_name
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
try:
|
||||
fea.load_results()
|
||||
except:
|
||||
QApplication.restoreOverrideCursor()
|
||||
majorVersion, minorVersion = fea.get_ccx_version()
|
||||
if majorVersion == 2 and minorVersion <= 10:
|
||||
message = "The used CalculiX version {}.{} creates broken output files.\n" \
|
||||
"Please upgrade to a newer version.".format(majorVersion, minorVersion)
|
||||
QtGui.QMessageBox.warning(None, "Upgrade CalculiX", message)
|
||||
raise
|
||||
else:
|
||||
QApplication.restoreOverrideCursor()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def choose_working_dir(self):
|
||||
current_wd = self.setup_working_dir()
|
||||
wd = QtGui.QFileDialog.getExistingDirectory(None, 'Choose CalculiX working directory',
|
||||
current_wd)
|
||||
if wd:
|
||||
self.solver_object.WorkingDir = wd
|
||||
else:
|
||||
self.solver_object.WorkingDir = current_wd
|
||||
self.form.le_working_dir.setText(self.solver_object.WorkingDir)
|
||||
|
||||
def write_input_file_handler(self):
|
||||
self.Start = time.time()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
QApplication.restoreOverrideCursor()
|
||||
if self.check_prerequisites_helper():
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
self.inp_file_name = ""
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.set_analysis_type(self.solver_object.AnalysisType)
|
||||
fea.update_objects()
|
||||
fea.write_inp_file()
|
||||
if fea.inp_file_name != "":
|
||||
self.inp_file_name = fea.inp_file_name
|
||||
self.femConsoleMessage("Write completed.")
|
||||
self.form.pb_edit_inp.setEnabled(True)
|
||||
self.form.pb_run_ccx.setEnabled(True)
|
||||
else:
|
||||
self.femConsoleMessage("Write .inp file failed!", "#FF0000")
|
||||
QApplication.restoreOverrideCursor()
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
def check_prerequisites_helper(self):
|
||||
self.Start = time.time()
|
||||
self.femConsoleMessage("Check dependencies...")
|
||||
self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start))
|
||||
|
||||
fea = FemToolsCcx.FemToolsCcx(None, self.solver_object)
|
||||
fea.update_objects()
|
||||
message = fea.check_prerequisites()
|
||||
if message != "":
|
||||
QtGui.QMessageBox.critical(None, "Missing prerequisit(s)", message)
|
||||
return False
|
||||
return True
|
||||
|
||||
def start_ext_editor(self, ext_editor_path, filename):
|
||||
if not hasattr(self, "ext_editor_process"):
|
||||
self.ext_editor_process = QtCore.QProcess()
|
||||
if self.ext_editor_process.state() != QtCore.QProcess.Running:
|
||||
self.ext_editor_process.start(ext_editor_path, [filename])
|
||||
|
||||
def editCalculixInputFile(self):
|
||||
print ('editCalculixInputFile {}'.format(self.inp_file_name))
|
||||
if self.ccx_prefs.GetBool("UseInternalEditor", True):
|
||||
FemGui.open(self.inp_file_name)
|
||||
else:
|
||||
ext_editor_path = self.ccx_prefs.GetString("ExternalEditorPath", "")
|
||||
if ext_editor_path:
|
||||
self.start_ext_editor(ext_editor_path, self.inp_file_name)
|
||||
else:
|
||||
print ("External editor is not defined in FEM preferences. Falling back to internal editor")
|
||||
FemGui.open(self.inp_file_name)
|
||||
|
||||
def runCalculix(self):
|
||||
print ('runCalculix')
|
||||
self.Start = time.time()
|
||||
|
||||
self.femConsoleMessage("CalculiX binary: {}".format(self.CalculixBinary))
|
||||
self.femConsoleMessage("Run CalculiX...")
|
||||
|
||||
# run Calculix
|
||||
print ('run CalculiX at: {} with: {}'.format(self.CalculixBinary, os.path.splitext(self.inp_file_name)[0]))
|
||||
# change cwd because ccx may crash if directory has no write permission
|
||||
# there is also a limit of the length of file names so jump to the document directory
|
||||
self.cwd = QtCore.QDir.currentPath()
|
||||
fi = QtCore.QFileInfo(self.inp_file_name)
|
||||
QtCore.QDir.setCurrent(fi.path())
|
||||
self.Calculix.start(self.CalculixBinary, ['-i', fi.baseName()])
|
||||
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
def select_analysis_type(self, analysis_type):
|
||||
if self.solver_object.AnalysisType != analysis_type:
|
||||
self.solver_object.AnalysisType = analysis_type
|
||||
self.form.pb_edit_inp.setEnabled(False)
|
||||
self.form.pb_run_ccx.setEnabled(False)
|
||||
|
||||
def select_static_analysis(self):
|
||||
self.select_analysis_type('static')
|
||||
|
||||
def select_frequency_analysis(self):
|
||||
self.select_analysis_type('frequency')
|
||||
|
||||
def select_thermomech_analysis(self):
|
||||
self.select_analysis_type('thermomech')
|
||||
|
||||
# That function overlaps with FemToolsCcx setup_working_dir and could be removed when the one from FemToolsCcx would be used
|
||||
def setup_working_dir(self):
|
||||
wd = self.solver_object.WorkingDir
|
||||
if not (os.path.isdir(wd)):
|
||||
try:
|
||||
os.makedirs(wd)
|
||||
except:
|
||||
print ("Dir \'{}\' from FEM preferences doesn't exist and cannot be created.".format(wd))
|
||||
import tempfile
|
||||
wd = tempfile.gettempdir()
|
||||
print ("Dir \'{}\' will be used instead.".format(wd))
|
||||
return wd
|
||||
|
||||
Reference in New Issue
Block a user