diff --git a/src/Mod/Fem/Gui/Resources/ui/ElementGeometry1D.ui b/src/Mod/Fem/Gui/Resources/ui/ElementGeometry1D.ui index 00387d2881..0c3559333b 100644 --- a/src/Mod/Fem/Gui/Resources/ui/ElementGeometry1D.ui +++ b/src/Mod/Fem/Gui/Resources/ui/ElementGeometry1D.ui @@ -20,46 +20,16 @@ Cross section parameter - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - + 2 - + - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - @@ -121,23 +91,8 @@ - + - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - @@ -173,7 +128,7 @@ - + @@ -236,6 +191,284 @@ + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Axis1 Length: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + Axis2 Length: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Height: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + Width: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + 0.000000000000000 + + + + + + + T1 Thickness: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + T2 Thickness: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + T3 Thickness: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + T4 Thickness: + + + + + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + 1.000000000000000 + + + 1000000000.000000000000000 + + + 0.000000000000000 + + + mm + + + 2 + + + 0.000000000000000 + + + + + + + @@ -266,7 +499,7 @@ - cb_crosssectiontype + cb_cross_section_type currentIndexChanged(int) widget_stack setCurrentIndex(int) diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index bd0eb7d301..ad8963d760 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -351,7 +351,7 @@ def makeElementFluid1D(doc, name="ElementFluid1D"): def makeElementGeometry1D( - doc, sectiontype="Rectangular", width=10.0, height=25.0, name="ElementGeometry1D" + doc, sectiontype="Rectangular", width=10.0, height=25.0, thickness=2.0, name="ElementGeometry1D" ): """makeElementGeometry1D(document, [width], [height], [name]): creates a 1D geometry element object to define a cross section""" @@ -359,17 +359,22 @@ def makeElementGeometry1D( from femobjects import element_geometry1D element_geometry1D.ElementGeometry1D(obj) - sec_types = element_geometry1D.ElementGeometry1D.known_beam_types - if sectiontype not in sec_types: - FreeCAD.Console.PrintError("Section type is unknown. Set to " + sec_types[0] + " \n") - obj.SectionType = sec_types[0] - else: - obj.SectionType = sectiontype + + obj.SectionType = sectiontype obj.RectWidth = width obj.RectHeight = height obj.CircDiameter = height obj.PipeDiameter = height - obj.PipeThickness = width + obj.PipeThickness = thickness + obj.Axis1Length = width + obj.Axis2Length = height + obj.BoxHeight = height + obj.BoxWidth = width + obj.BoxT1 = thickness + obj.BoxT2 = thickness + obj.BoxT3 = thickness + obj.BoxT4 = thickness + if FreeCAD.GuiUp: from femviewprovider import view_element_geometry1D diff --git a/src/Mod/Fem/femobjects/element_geometry1D.py b/src/Mod/Fem/femobjects/element_geometry1D.py index 6ab731e37d..4d30631b8c 100644 --- a/src/Mod/Fem/femobjects/element_geometry1D.py +++ b/src/Mod/Fem/femobjects/element_geometry1D.py @@ -29,7 +29,11 @@ __url__ = "https://www.freecad.org" # \ingroup FEM # \brief element geometry 1D object +from FreeCAD import Base from . import base_femelement +from . import base_fempythonobject + +_PropHelper = base_fempythonobject._PropHelper class ElementGeometry1D(base_femelement.BaseFemElement): @@ -38,55 +42,150 @@ class ElementGeometry1D(base_femelement.BaseFemElement): """ Type = "Fem::ElementGeometry1D" - known_beam_types = ["Rectangular", "Circular", "Pipe"] def __init__(self, obj): super().__init__(obj) - obj.addProperty( - "App::PropertyLength", - "RectWidth", - "RectBeamSection", - "set width of the rectangular beam elements", - ) - obj.setPropertyStatus("RectWidth", "LockDynamic") + def _get_properties(self): + prop = super()._get_properties() - obj.addProperty( - "App::PropertyLength", - "RectHeight", - "RectBeamSection", - "set height of therectangular beam elements", + prop.append( + _PropHelper( + type="App::PropertyLength", + name="RectWidth", + group="RectBeamSection", + doc="Set width of the rectangular beam elements", + value=0.0, + ) ) - obj.setPropertyStatus("RectHeight", "LockDynamic") - - obj.addProperty( - "App::PropertyLength", - "CircDiameter", - "CircBeamSection", - "set diameter of the circular beam elements", + prop.append( + _PropHelper( + type="App::PropertyLength", + name="RectHeight", + group="RectBeamSection", + doc="Set height of there ctangular beam elements", + value=0.0, + ) ) - obj.setPropertyStatus("CircDiameter", "LockDynamic") - - obj.addProperty( - "App::PropertyLength", - "PipeDiameter", - "PipeBeamSection", - "set outer diameter of the pipe beam elements", + prop.append( + _PropHelper( + type="App::PropertyLength", + name="CircDiameter", + group="CircBeamSection", + doc="Set diameter of the circular beam elements", + value=0.0, + ) ) - obj.setPropertyStatus("PipeDiameter", "LockDynamic") - - obj.addProperty( - "App::PropertyLength", - "PipeThickness", - "PipeBeamSection", - "set thickness of the pipe beam elements", + prop.append( + _PropHelper( + type="App::PropertyLength", + name="PipeDiameter", + group="PipeBeamSection", + doc="Set outer diameter of the pipe beam elements", + value=0.0, + ) ) - obj.setPropertyStatus("PipeThickness", "LockDynamic") - - obj.addProperty( - "App::PropertyEnumeration", "SectionType", "BeamSection", "select beam section type" + prop.append( + _PropHelper( + type="App::PropertyLength", + name="PipeThickness", + group="PipeBeamSection", + doc="Set thickness of the pipe beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="Axis1Length", + group="EllipticalBeamSection", + doc="Set first principal axis length of the elliptical beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="Axis2Length", + group="EllipticalBeamSection", + doc="Set second principal axis length of the elliptical beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxWidth", + group="BoxBeamSection", + doc="Set width of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxHeight", + group="BoxBeamSection", + doc="Set height of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxT1", + group="BoxBeamSection", + doc="Set thickness parameter t1 of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxT2", + group="BoxBeamSection", + doc="Set thickness parameter t2 of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxT3", + group="BoxBeamSection", + doc="Set thickness parameter t3 of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyLength", + name="BoxT4", + group="BoxBeamSection", + doc="Set thickness parameter t4 of the box beam elements", + value=0.0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="SectionType", + group="BeamSection", + doc="Select beam section type", + value=["Rectangular", "Circular", "Pipe", "Elliptical", "Box"], + ) ) - obj.setPropertyStatus("SectionType", "LockDynamic") - obj.SectionType = ElementGeometry1D.known_beam_types - obj.SectionType = "Rectangular" + return prop + + def onDocumentRestored(self, obj): + # update old project with new properties + for prop in self._get_properties(): + try: + obj.getPropertyByName(prop.name) + except Base.PropertyError: + prop.add_to_object(obj) + + if prop.name == "SectionType": + # refresh the list of known section types for old projects + obj.SectionType = prop.value diff --git a/src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py b/src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py index c7ee293538..12f672e2b2 100644 --- a/src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py +++ b/src/Mod/Fem/femsolver/calculix/write_femelement_geometry.py @@ -45,7 +45,6 @@ def write_femelement_geometry(f, ccxwriter): section_nor = "{:.13G}, {:.13G}, {:.13G}\n".format( beam_axis_m[0], beam_axis_m[1], beam_axis_m[2] ) - print(section_nor) if beamsec_obj.SectionType == "Rectangular": # see meshtools.get_beam_main_axis_m(beam_direction, defined_angle) # the method get_beam_main_axis_m() which calculates the beam_axis_m vector @@ -66,12 +65,29 @@ def write_femelement_geometry(f, ccxwriter): section_type = ", SECTION=CIRC" section_geo = f"{diameter:.13G}\n" section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n" + elif beamsec_obj.SectionType == "Elliptical": + axis1 = beamsec_obj.Axis1Length.getValueAs("mm").Value + axis2 = beamsec_obj.Axis2Length.getValueAs("mm").Value + section_type = ", SECTION=CIRC" + section_geo = f"{axis1:.13G},{axis2:.13G}\n" + section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n" elif beamsec_obj.SectionType == "Pipe": radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs("mm").Value thickness = beamsec_obj.PipeThickness.getValueAs("mm").Value section_type = ", SECTION=PIPE" section_geo = f"{radius:.13G},{thickness:.13G}\n" section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n" + elif beamsec_obj.SectionType == "Box": + box_width = beamsec_obj.BoxWidth.getValueAs("mm").Value + box_height = beamsec_obj.BoxHeight.getValueAs("mm").Value + box_t1 = beamsec_obj.BoxT1.getValueAs("mm").Value + box_t2 = beamsec_obj.BoxT2.getValueAs("mm").Value + box_t3 = beamsec_obj.BoxT3.getValueAs("mm").Value + box_t4 = beamsec_obj.BoxT4.getValueAs("mm").Value + section_type = ", SECTION=BOX" + section_geo = f"{box_width:.13G},{box_height:.13G},{box_t1:.13G},{box_t2:.13G},{box_t3:.13G},{box_t4:.13G}\n" + section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n" + f.write(section_def) f.write(section_geo) f.write(section_nor) diff --git a/src/Mod/Fem/femtaskpanels/task_element_geometry1D.py b/src/Mod/Fem/femtaskpanels/task_element_geometry1D.py index 08f3a39d1d..dffaae01fc 100644 --- a/src/Mod/Fem/femtaskpanels/task_element_geometry1D.py +++ b/src/Mod/Fem/femtaskpanels/task_element_geometry1D.py @@ -52,7 +52,7 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElementGeometry1D.ui" ) QtCore.QObject.connect( - self.parameter_widget.cb_crosssectiontype, + self.parameter_widget.cb_cross_section_type, QtCore.SIGNAL("activated(int)"), self.sectiontype_changed, ) @@ -81,10 +81,51 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.pipe_thickness_changed, ) - - self.parameter_widget.cb_crosssectiontype.addItems( - element_geometry1D.ElementGeometry1D.known_beam_types + QtCore.QObject.connect( + self.parameter_widget.qsb_elliptical_axis1, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.elliptical_axis1_changed, ) + QtCore.QObject.connect( + self.parameter_widget.qsb_elliptical_axis2, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.elliptical_axis2_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_height, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_height_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_width, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_width_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_t1, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_t1_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_t2, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_t2_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_t3, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_t3_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_box_t4, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.box_t4_changed, + ) + + self.parameter_widget.cb_cross_section_type.addItems( + obj.getEnumerationsOfProperty("SectionType") + ) + self.get_beamsection_props() self.update_parameter_widget() @@ -113,6 +154,14 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.circ_diameter = self.obj.CircDiameter self.pipe_diameter = self.obj.PipeDiameter self.pipe_thickness = self.obj.PipeThickness + self.axis1_length = self.obj.Axis1Length + self.axis2_length = self.obj.Axis2Length + self.box_height = self.obj.BoxHeight + self.box_width = self.obj.BoxWidth + self.box_t1 = self.obj.BoxT1 + self.box_t2 = self.obj.BoxT2 + self.box_t3 = self.obj.BoxT3 + self.box_t4 = self.obj.BoxT4 def set_beamsection_props(self): self.obj.SectionType = self.section_type @@ -121,15 +170,17 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): self.obj.CircDiameter = self.circ_diameter self.obj.PipeDiameter = self.pipe_diameter self.obj.PipeThickness = self.pipe_thickness + self.obj.Axis1Length = self.axis1_length + self.obj.Axis2Length = self.axis2_length + self.obj.BoxHeight = self.box_height + self.obj.BoxWidth = self.box_width + self.obj.BoxT1 = self.box_t1 + self.obj.BoxT2 = self.box_t2 + self.obj.BoxT3 = self.box_t3 + self.obj.BoxT4 = self.box_t4 def update_parameter_widget(self): "fills the widgets" - self.rect_height = self.obj.RectHeight - self.rect_width = self.obj.RectWidth - self.circ_diameter = self.obj.CircDiameter - self.pipe_diameter = self.obj.PipeDiameter - self.pipe_thickness = self.obj.PipeThickness - FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_rec_height).bind( self.obj, "RectHeight" ) @@ -153,16 +204,42 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): ) self.parameter_widget.qsb_pipe_thickness.setProperty("value", self.pipe_thickness) - index_crosssectiontype = self.parameter_widget.cb_crosssectiontype.findText( + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_elliptical_axis1).bind( + self.obj, "Axis1Length" + ) + self.parameter_widget.qsb_elliptical_axis1.setProperty("value", self.axis1_length) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_elliptical_axis2).bind( + self.obj, "Axis2Length" + ) + self.parameter_widget.qsb_elliptical_axis2.setProperty("value", self.axis2_length) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_height).bind( + self.obj, "BoxHeight" + ) + self.parameter_widget.qsb_box_height.setProperty("value", self.box_height) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_width).bind(self.obj, "BoxWidth") + self.parameter_widget.qsb_box_width.setProperty("value", self.box_width) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_t1).bind(self.obj, "BoxT1") + self.parameter_widget.qsb_box_t1.setProperty("value", self.box_t1) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_t2).bind(self.obj, "BoxT2") + self.parameter_widget.qsb_box_t2.setProperty("value", self.box_t2) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_t3).bind(self.obj, "BoxT3") + self.parameter_widget.qsb_box_t3.setProperty("value", self.box_t3) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_box_t4).bind(self.obj, "BoxT4") + self.parameter_widget.qsb_box_t4.setProperty("value", self.box_t4) + + index_cross_section_type = self.parameter_widget.cb_cross_section_type.findText( self.section_type ) - self.parameter_widget.cb_crosssectiontype.setCurrentIndex(index_crosssectiontype) + self.parameter_widget.cb_cross_section_type.setCurrentIndex(index_cross_section_type) def sectiontype_changed(self, index): if index < 0: return - self.parameter_widget.cb_crosssectiontype.setCurrentIndex(index) - self.section_type = self.parameter_widget.cb_crosssectiontype.itemText(index) + self.parameter_widget.cb_cross_section_type.setCurrentIndex(index) + self.section_type = self.parameter_widget.cb_cross_section_type.itemText(index) def rec_height_changed(self, base_quantity_value): self.rect_height = base_quantity_value @@ -178,3 +255,27 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): def pipe_thickness_changed(self, base_quantity_value): self.pipe_thickness = base_quantity_value + + def elliptical_axis1_changed(self, base_quantity_value): + self.axis1_length = base_quantity_value + + def elliptical_axis2_changed(self, base_quantity_value): + self.axis2_length = base_quantity_value + + def box_height_changed(self, base_quantity_value): + self.box_height = base_quantity_value + + def box_width_changed(self, base_quantity_value): + self.box_width = base_quantity_value + + def box_t1_changed(self, base_quantity_value): + self.box_t1 = base_quantity_value + + def box_t2_changed(self, base_quantity_value): + self.box_t2 = base_quantity_value + + def box_t3_changed(self, base_quantity_value): + self.box_t3 = base_quantity_value + + def box_t4_changed(self, base_quantity_value): + self.box_t4 = base_quantity_value