Merge pull request #350 from berndhahnebach/bhbdev057

New tool to onvert surface of FEMMeshes to a Mesh
This commit is contained in:
wwmayer
2016-11-26 15:48:52 +01:00
committed by GitHub
26 changed files with 526 additions and 81 deletions

View File

@@ -68,6 +68,9 @@ SET(FemScripts_SRCS
_CommandBeamSection.py
_CommandControlSolver.py
_CommandConstraintSelfWeight.py
_CommandFEMMesh2Mesh.py
_CommandMechanicalMaterial.py
_CommandShowResult.py
_CommandMaterialMechanicalNonlinear.py
_CommandMechanicalMaterial.py
_CommandMeshGmshFromShape.py
@@ -116,6 +119,7 @@ SET(FemScripts_SRCS
FemInputWriterCcx.py
FemInputWriterZ88.py
FemMaterialMechanicalNonlinear.py
FemMesh2Mesh.py
FemMeshGmsh.py
FemMeshTools.py
FemShellThickness.py

View File

@@ -45,6 +45,9 @@ INSTALL(
FemGmshTools.py
FemMesh2Mesh.py
_CommandFEMMesh2Mesh.py
FemBeamSection.py
_FemBeamSection.py
_ViewProviderFemBeamSection.py

View File

@@ -58,6 +58,10 @@ class FemCommands(object):
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc() and self.results_present()
elif self.is_active == 'with_part_feature':
active = FreeCADGui.ActiveDocument is not None and self.part_feature_selected()
elif self.is_active == 'with_femmesh':
active = FreeCADGui.ActiveDocument is not None and self.femmesh_selected()
elif self.is_active == 'with_femmesh_andor_res':
active = FreeCADGui.ActiveDocument is not None and self.with_femmesh_andor_res_selected()
elif self.is_active == 'with_material':
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc() and self.material_selected()
elif self.is_active == 'with_solver':
@@ -81,6 +85,13 @@ class FemCommands(object):
else:
return False
def femmesh_selected(self):
sel = FreeCADGui.Selection.getSelection()
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
return True
else:
return False
def material_selected(self):
sel = FreeCADGui.Selection.getSelection()
if len(sel) == 1 and sel[0].isDerivedFrom("App::MaterialObjectPython"):
@@ -88,6 +99,26 @@ class FemCommands(object):
else:
return False
def with_femmesh_andor_res_selected(self):
sel = FreeCADGui.Selection.getSelection()
if len(sel) == 1 and sel[0].isDerivedFrom("Fem::FemMeshObject"):
return True
elif len(sel) == 2:
if(sel[0].isDerivedFrom("Fem::FemMeshObject")):
if(sel[1].isDerivedFrom("Fem::FemResultObject")):
return True
else:
return False
elif(sel[1].isDerivedFrom("Fem::FemMeshObject")):
if(sel[0].isDerivedFrom("Fem::FemResultObject")):
return True
else:
return False
else:
return False
else:
return False
def active_analysis_in_active_doc(self):
return FemGui.getActiveAnalysis().Document is FreeCAD.ActiveDocument

View File

@@ -29,6 +29,7 @@ __url__ = "http://www.freecadweb.org"
import FreeCAD
import Fem
import Units
import subprocess
import tempfile
from platform import system
@@ -48,12 +49,12 @@ class FemGmshTools():
self.part_obj = self.mesh_obj.Part
# clmax, ElementSizeMax: float, 0.0 = 1e+22
self.clmax = self.mesh_obj.ElementSizeMax
self.clmax = Units.Quantity(self.mesh_obj.ElementSizeMax).Value
if self.clmax == 0.0:
self.clmax = 1e+22
# clmin, ElementSizeMin: float
self.clmin = self.mesh_obj.ElementSizeMin
self.clmin = Units.Quantity(self.mesh_obj.ElementSizeMin).Value
# order, ElementOrder: ['Auto', '1st', '2nd']
self.order = self.mesh_obj.ElementOrder

176
src/Mod/Fem/FemMesh2Mesh.py Normal file
View File

@@ -0,0 +1,176 @@
# ***************************************************************************
# * *
# * Copyright (c) 2016 - Frantisek Loeffelmann <LoffF@email.cz> *
# * *
# * 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__ = "FemMesh to Mesh converter"
__author__ = "Frantisek Loeffelmann, Ulrich Brammer, Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
## @package FwmMesh2Mesh
# \ingroup FEM
import time
# import Mesh
'''
load FreeCADs 3D FEM example from Start Workbench
femmesh = App.ActiveDocument.getObject("Box_Mesh").FemMesh
result = App.ActiveDocument.getObject("CalculiX_static_results")
import FemMesh2Mesh
out_mesh = FemMesh2Mesh.femmesh_2_mesh(femmesh, result)
import Mesh
Mesh.show(Mesh.Mesh(out_mesh))
'''
# These dictionaries list the nodes, that define faces of an element.
# The key is the face number, used internally by FreeCAD.
# The list contains the nodes in the element for each face.
tetFaces = {
1: [0, 1, 2],
2: [0, 3, 1],
3: [1, 3, 2],
4: [2, 3, 0]}
pentaFaces = {
1: [0, 1, 2],
2: [3, 5, 4],
3: [0, 3, 4, 1],
4: [1, 4, 5, 2],
5: [0, 2, 5, 3]}
hexaFaces = { # hexa8 or hexa20 (ignoring mid-nodes)
1: [0, 1, 2, 3],
2: [4, 7, 6, 5],
3: [0, 4, 5, 1],
4: [1, 5, 6, 2],
5: [2, 6, 7, 3],
6: [3, 7, 4, 0]}
pyraFaces = { # pyra5 or pyra13 (ignoring mid-nodes)
1: [0, 1, 2, 3],
2: [0, 4, 1],
3: [1, 4, 2],
4: [2, 4, 3],
5: [3, 4, 0]}
face_dicts = {
4: tetFaces,
5: pyraFaces,
6: pentaFaces,
8: hexaFaces,
10: tetFaces,
13: pyraFaces,
15: pentaFaces,
20: hexaFaces}
def femmesh_2_mesh(myFemMesh, myResults=None):
shiftBits = 20 # allows a million nodes, needs to be higher for more nodes in a FemMesh
# This code generates a dict and a faceCode for each face of all elements
# All faceCodes are than sorted.
start_time = time.clock()
faceCodeList = []
faceCodeDict = {}
for ele in myFemMesh.Volumes:
element_nodes = myFemMesh.getElementNodes(ele)
# print 'element_node: ', element_nodes
faceDef = face_dicts[len(element_nodes)]
for key in faceDef:
nodeList = []
codeList = []
faceCode = 0
shifter = 0
for nodeIdx in faceDef[key]:
nodeList.append(element_nodes[nodeIdx])
codeList.append(element_nodes[nodeIdx])
codeList.sort()
for node in codeList:
faceCode += (node << shifter)
# x << n: x shifted left by n bits = Multiplication
shifter += shiftBits
# print 'codeList: ', codeList
faceCodeDict[faceCode] = nodeList
faceCodeList.append(faceCode)
faceCodeList.sort()
allFaces = len(faceCodeList)
actFaceIdx = 0
singleFaces = []
# Here we search for faces, which do not have a counterpart.
# These are the faces on the surface of the mesh.
while actFaceIdx < allFaces:
if actFaceIdx < (allFaces - 1):
if faceCodeList[actFaceIdx] == faceCodeList[actFaceIdx + 1]:
actFaceIdx += 2
else:
# print 'found a single Face: ', faceCodeList[actFaceIdx]
singleFaces.append(faceCodeList[actFaceIdx])
actFaceIdx += 1
else:
print 'found a last Face: ', faceCodeList[actFaceIdx]
singleFaces.append(faceCodeList[actFaceIdx])
actFaceIdx += 1
output_mesh = []
if myResults:
print(myResults.Name)
for myFace in singleFaces:
face_nodes = faceCodeDict[myFace]
dispVec0 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[0])]
dispVec1 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[1])]
dispVec2 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[2])]
triangle = [myFemMesh.getNodeById(face_nodes[0]) + dispVec0,
myFemMesh.getNodeById(face_nodes[1]) + dispVec1,
myFemMesh.getNodeById(face_nodes[2]) + dispVec2]
output_mesh.extend(triangle)
# print 'my triangle: ', triangle
if len(face_nodes) == 4:
dispVec3 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[3])]
triangle = [myFemMesh.getNodeById(face_nodes[2]) + dispVec2,
myFemMesh.getNodeById(face_nodes[3]) + dispVec3,
myFemMesh.getNodeById(face_nodes[0]) + dispVec0]
output_mesh.extend(triangle)
# print 'my 2. triangle: ', triangle
else:
for myFace in singleFaces:
face_nodes = faceCodeDict[myFace]
triangle = [myFemMesh.getNodeById(face_nodes[0]),
myFemMesh.getNodeById(face_nodes[1]),
myFemMesh.getNodeById(face_nodes[2])]
output_mesh.extend(triangle)
# print 'my triangle: ', triangle
if len(face_nodes) == 4:
triangle = [myFemMesh.getNodeById(face_nodes[2]),
myFemMesh.getNodeById(face_nodes[3]),
myFemMesh.getNodeById(face_nodes[0])]
output_mesh.extend(triangle)
# print 'my 2. triangle: ', triangle
end_time = time.clock()
print 'Mesh by surface search method: ', end_time - start_time
return output_mesh

View File

@@ -1,54 +1,58 @@
<RCC>
<qresource>
<file>icons/fem-fem-mesh-from-shape.svg</file>
<file>icons/fem-fem-mesh-gmsh-from-shape.svg</file>
<file>icons/fem-fem-mesh-netgen-from-shape.svg</file>
<file>icons/fem-fem-mesh-create-node-by-poly.svg</file>
<file>icons/fem-analysis.svg</file>
<file>icons/fem-cfd-analysis.svg</file>
<file>icons/fem-constraint-fluid-boundary.svg</file>
<file>icons/fem-solver.svg</file>
<file>icons/fem-constraint-displacement.svg</file>
<file>icons/fem-constraint-selfweight.svg</file>
<file>icons/fem-constraint-temperature.svg</file>
<file>icons/fem-constraint-InitialTemperature.svg</file>
<file>icons/fem-constraint-force.svg</file>
<file>icons/fem-constraint-fixed.svg</file>
<file>icons/fem-constraint-planerotation.svg</file>
<file>icons/fem-constraint-pressure.svg</file>
<file>icons/fem-constraint-heatflux.svg</file>
<file>icons/fem-constraint-bearing.svg</file>
<file>icons/fem-constraint-gear.svg</file>
<file>icons/fem-constraint-pulley.svg</file>
<file>icons/fem-constraint-contact.svg</file>
<file>icons/fem-constraint-transform.svg</file>
<file>icons/fem-add-fem-mesh.svg</file>
<file>icons/fem-add-material.svg</file>
<file>icons/fem-add-part.svg</file>
<file>icons/fem-analysis.svg</file>
<file>icons/fem-beam-section.svg</file>
<file>icons/fem-box.svg</file>
<file>icons/fem-cfd-analysis.svg</file>
<file>icons/fem-constraint-bearing.svg</file>
<file>icons/fem-constraint-contact.svg</file>
<file>icons/fem-constraint-displacement.svg</file>
<file>icons/fem-constraint-fixed.svg</file>
<file>icons/fem-constraint-fluid-boundary.svg</file>
<file>icons/fem-constraint-force.svg</file>
<file>icons/fem-constraint-gear.svg</file>
<file>icons/fem-constraint-heatflux.svg</file>
<file>icons/fem-constraint-InitialTemperature.svg</file>
<file>icons/fem-constraint-planerotation.svg</file>
<file>icons/fem-constraint-pressure.svg</file>
<file>icons/fem-constraint-pulley.svg</file>
<file>icons/fem-constraint-selfweight.svg</file>
<file>icons/fem-constraint-temperature.svg</file>
<file>icons/fem-constraint-transform.svg</file>
<file>icons/fem-control-solver.svg</file>
<file>icons/fem-cylinder.svg</file>
<file>icons/fem-data.png</file>
<file>icons/fem-fem-mesh-create-node-by-poly.svg</file>
<file>icons/fem-fem-mesh-from-shape.svg</file>
<file>icons/fem-fem-mesh-gmsh-from-shape.svg</file>
<file>icons/fem-fem-mesh-netgen-from-shape.svg</file>
<file>icons/fem-femmesh-to-mesh.svg</file>
<file>icons/fem-frequency-analysis.svg</file>
<file>icons/fem-inp-editor.svg</file>
<file>icons/fem-material.svg</file>
<file>icons/fem-material-nonlinear.svg</file>
<file>icons/fem-control-solver.svg</file>
<file>icons/fem-plane.svg</file>
<file>icons/fem-purge-results.svg</file>
<file>icons/fem-run-solver.svg</file>
<file>icons/fem-frequency-analysis.svg</file>
<file>icons/fem-thermomechanical-analysis.svg</file>
<file>icons/fem-static-analysis.svg</file>
<file>icons/fem-result.svg</file>
<file>icons/fem-run-solver.svg</file>
<file>icons/fem-shell-thickness.svg</file>
<file>icons/fem-beam-section.svg</file>
<file>icons/preferences-fem.svg</file>
<file>icons/fem-solver.svg</file>
<file>icons/fem-sphere.svg</file>
<file>icons/fem-static-analysis.svg</file>
<file>icons/fem-thermomechanical-analysis.svg</file>
<file>icons/FemWorkbench.svg</file>
<file>icons/preferences-fem.svg</file>
<file>icons/fem-clip.png</file>
<file>icons/fem-clip-scalar.png</file>
<file>icons/fem-cut.png</file>
<file>icons/fem-isosurface.png</file>
<file>icons/fem-warp.png</file>
<file>icons/fem-data.png</file>
<file>icons/fem-plane.svg</file>
<file>icons/fem-box.svg</file>
<file>icons/fem-sphere.svg</file>
<file>icons/fem-cylinder.svg</file>
<file>translations/Fem_af.qm</file>
<file>translations/Fem_de.qm</file>
<file>translations/Fem_fi.qm</file>

View File

@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 64 64.000001"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="fem-femmesh-to-mesh.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.8044993"
inkscape:cx="76.468063"
inkscape:cy="12.180925"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1316"
inkscape:window-height="955"
inkscape:window-x="759"
inkscape:window-y="132"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Vrstva 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-988.3622)">
<g
id="g4384"
style="stroke-width:0.875;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.9993599,0,0,1.0726383,-363.31737,897.73174)">
<rect
y="97.897186"
x="369.3476"
height="18.334955"
width="19.565931"
id="rect4179-7-4"
style="fill:#ffdd55;fill-opacity:1;stroke:#000000;stroke-width:0.875;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
transform="matrix(1,0,-0.91292128,0.40813569,0,0)"
y="223.7533"
x="588.09558"
height="15.784455"
width="19.614277"
id="rect4179-8-8-3"
style="fill:#ffcc00;fill-opacity:1;stroke:#000000;stroke-width:1.36963785;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
transform="matrix(0.91327018,-0.40735437,0,1,0,0)"
y="271.60327"
x="426.50433"
height="18.205898"
width="15.631971"
id="rect4179-0-7-6"
style="fill:#d4aa00;fill-opacity:1;stroke:#000000;stroke-width:0.91560555;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4234-0-2"
d="m 369.48663,97.980311 19.48661,18.124999"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path4236-9-5"
d="m 402.99109,91.819601 -13.75,24.017849"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path4238-9-7"
d="m 370.04466,97.801741 32.76786,-6.25"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
<path
style="fill:#ff7f2a;fill-rule:evenodd;stroke:none"
d="m 8.1764497,1033.4611 -2.58439,3.8079 10.8144803,8.9124 -1.58101,2.3295 9.28162,1.0828 -3.68721,-9.3257 -1.429,2.1055 -10.8144903,-8.9124"
id="path4374"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<g
id="g4376"
transform="matrix(0.9993599,0,0,1.0726383,-374.13469,898.15064)"
style="stroke-width:0.875;stroke-miterlimit:4;stroke-dasharray:none">
<rect
y="119.32574"
x="397.91901"
height="18.334955"
width="19.565931"
id="rect4179-07"
style="fill:#80ff80;fill-opacity:1;stroke:#000000;stroke-width:0.875;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
transform="matrix(1,0,-0.91292128,0.40813569,0,0)"
y="276.2569"
x="664.59863"
height="15.784455"
width="19.614277"
id="rect4179-8-7"
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1.36963785;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
transform="matrix(0.91327018,-0.40735437,0,1,0,0)"
y="305.77585"
x="457.78909"
height="18.205898"
width="15.631971"
id="rect4179-0-8"
style="fill:#00aa00;fill-opacity:1;stroke:#000000;stroke-width:0.91560555;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4234-06"
d="m 398.05806,119.40889 19.48661,18.125"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path4236-3"
d="m 431.56252,113.24818 -13.75,24.01785"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
inkscape:connector-curvature="0"
id="path4238-7"
d="m 398.61609,119.23032 32.76786,-6.25"
style="fill:none;stroke:#000000;stroke-width:0.875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -55,7 +55,8 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem* root = StdWorkbench::setupToolBars();
Gui::ToolBarItem* fem = new Gui::ToolBarItem(root);
fem->setCommand("FEM");
*fem << "Fem_Analysis"
*fem << "Fem_FemMesh2Mesh"
<< "Fem_Analysis"
<< "Fem_SolverCalculix"
// << "Fem_SolverZ88"
<< "Fem_MeshNetgenFromShape"
@@ -113,10 +114,17 @@ Gui::MenuItem* Workbench::setupMenuBar() const
{
Gui::MenuItem* root = StdWorkbench::setupMenuBar();
Gui::MenuItem* item = root->findItem("&Windows");
Gui::MenuItem* util = new Gui::MenuItem;
util->setCommand("&Utilities");
*util << "Fem_FemMesh2Mesh";
Gui::MenuItem* fem = new Gui::MenuItem;
root->insertItem(item, fem);
fem->setCommand("&FEM");
*fem << "Fem_Analysis"
*fem << util
<< "Separator"
<< "Fem_Analysis"
<< "Fem_SolverCalculix"
<< "Fem_SolverZ88"
<< "Fem_MeshNetgenFromShape"

View File

@@ -49,6 +49,7 @@ class FemWorkbench (Workbench):
import _CommandRunSolver
import _CommandPurgeResults
import _CommandControlSolver
import _CommandFEMMesh2Mesh
import _CommandMeshGmshFromShape
import _CommandMeshNetgenFromShape
import _CommandAnalysis

View File

@@ -58,5 +58,4 @@ class _CommandAnalysis(FemCommands):
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [App.activeDocument()." + sel[0].Name + "]")
FreeCADGui.Selection.clearSelection()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_Analysis', _CommandAnalysis())
FreeCADGui.addCommand('Fem_Analysis', _CommandAnalysis())

View File

@@ -49,5 +49,4 @@ class _CommandBeamSection(FemCommands):
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemBeamSection.makeFemBeamSection()]")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_BeamSection', _CommandBeamSection())
FreeCADGui.addCommand('Fem_BeamSection', _CommandBeamSection())

View File

@@ -49,5 +49,4 @@ class _CommandConstraintSelfWeight(FemCommands):
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemConstraintSelfWeight.makeFemConstraintSelfWeight()]")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_ConstraintSelfWeight', _CommandConstraintSelfWeight())
FreeCADGui.addCommand('Fem_ConstraintSelfWeight', _CommandConstraintSelfWeight())

View File

@@ -27,7 +27,6 @@ __url__ = "http://www.freecadweb.org"
## @package CommandControlSolver
# \ingroup FEM
import FreeCAD
from FemCommands import FemCommands
import FreeCADGui
from PySide import QtCore
@@ -51,5 +50,4 @@ class _CommandControlSolver(FemCommands):
FreeCADGui.ActiveDocument.setEdit(solver_obj, 0)
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_ControlSolver', _CommandControlSolver())
FreeCADGui.addCommand('Fem_ControlSolver', _CommandControlSolver())

View File

@@ -0,0 +1,80 @@
# ***************************************************************************
# * *
# * 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__ = "Command FEMMesh to Mesh"
__author__ = "Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
## @package CommandFemMesh2Mesh
# \ingroup FEM
import FreeCAD
from FemCommands import FemCommands
import FreeCADGui
from PySide import QtCore
class _CommandFemMesh2Mesh(FemCommands):
# the Fem_FemMesh2Mesh command definition
def __init__(self):
super(_CommandFemMesh2Mesh, self).__init__()
self.resources = {'Pixmap': 'fem-femmesh-to-mesh',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Fem_FemMesh2Mesh", "FEM mesh to mesh"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Fem_FemMesh2Mesh", "Convert the surface of a FEM mesh to a mesh")}
self.is_active = 'with_femmesh_andor_res'
def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create FEM mesh")
FreeCADGui.addModule("FemGui")
sel = FreeCADGui.Selection.getSelection()
if (len(sel) == 1):
if(sel[0].isDerivedFrom("Fem::FemMeshObject")):
FreeCAD.ActiveDocument.openTransaction("Create Mesh from FEMMesh")
FreeCADGui.addModule("FemMesh2Mesh")
FreeCADGui.doCommand("out_mesh = FemMesh2Mesh.femmesh_2_mesh(App.ActiveDocument." + sel[0].Name + ".FemMesh)")
FreeCADGui.addModule("Mesh")
FreeCADGui.doCommand("Mesh.show(Mesh.Mesh(out_mesh))")
FreeCADGui.doCommand("App.ActiveDocument." + sel[0].Name + ".ViewObject.hide()")
if (len(sel) == 2):
femmesh = None
res = None
if(sel[0].isDerivedFrom("Fem::FemMeshObject")):
if(sel[1].isDerivedFrom("Fem::FemResultObject")):
femmesh = sel[0]
res = sel[1]
elif(sel[1].isDerivedFrom("Fem::FemMeshObject")):
if(sel[0].isDerivedFrom("Fem::FemResultObject")):
femmesh = sel[1]
res = sel[0]
if femmesh and res:
FreeCAD.ActiveDocument.openTransaction("Create Mesh from FEMMesh")
FreeCADGui.addModule("FemMesh2Mesh")
FreeCADGui.doCommand("out_mesh = FemMesh2Mesh.femmesh_2_mesh(App.ActiveDocument." + femmesh.Name + ".FemMesh, App.ActiveDocument." + res.Name + ")")
FreeCADGui.addModule("Mesh")
FreeCADGui.doCommand("Mesh.show(Mesh.Mesh(out_mesh))")
FreeCADGui.doCommand("App.ActiveDocument." + femmesh.Name + ".ViewObject.hide()")
FreeCADGui.Selection.clearSelection()
FreeCADGui.addCommand('Fem_FemMesh2Mesh', _CommandFemMesh2Mesh())

View File

@@ -74,5 +74,4 @@ class _CommandMaterialMechanicalNonlinear(FemCommands):
if solver_object and solver_object.SolverType == 'FemSolverCalculix':
solver_object.MaterialNonlinearity = "nonlinear"
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_MaterialMechanicalNonlinear', _CommandMaterialMechanicalNonlinear())
FreeCADGui.addCommand('Fem_MaterialMechanicalNonlinear', _CommandMaterialMechanicalNonlinear())

View File

@@ -55,5 +55,4 @@ class _CommandMechanicalMaterial(FemCommands):
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name)")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_MechanicalMaterial', _CommandMechanicalMaterial())
FreeCADGui.addCommand('Fem_MechanicalMaterial', _CommandMechanicalMaterial())

View File

@@ -61,5 +61,4 @@ class _CommandMeshGmshFromShape(FemCommands):
FreeCADGui.Selection.clearSelection()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_MeshGmshFromShape', _CommandMeshGmshFromShape())
FreeCADGui.addCommand('Fem_MeshGmshFromShape', _CommandMeshGmshFromShape())

View File

@@ -55,5 +55,4 @@ class _CommandMeshNetgenFromShape(FemCommands):
FreeCADGui.Selection.clearSelection()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_MeshNetgenFromShape', _CommandMeshNetgenFromShape())
FreeCADGui.addCommand('Fem_MeshNetgenFromShape', _CommandMeshNetgenFromShape())

View File

@@ -27,7 +27,6 @@ __url__ = "http://www.freecadweb.org"
## @package CommandPurgeResults
# \ingroup FEM
import FreeCAD
from FemCommands import FemCommands
import FemTools
import FreeCADGui
@@ -47,8 +46,7 @@ class _CommandPurgeResults(FemCommands):
def Activated(self):
fea = FemTools.FemTools()
fea.reset_all()
self.hide_meshes_show_parts_constraints()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_PurgeResults', _CommandPurgeResults())
FreeCADGui.addCommand('Fem_PurgeResults', _CommandPurgeResults())

View File

@@ -27,7 +27,6 @@ __url__ = "http://www.freecadweb.org"
## @package CommandRunSolver
# \ingroup FEM
import FreeCAD
from FemCommands import FemCommands
import FreeCADGui
from PySide import QtCore, QtGui
@@ -88,5 +87,4 @@ class _CommandRunSolver(FemCommands):
tp.restore_result_dialog()
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_RunSolver', _CommandRunSolver())
FreeCADGui.addCommand('Fem_RunSolver', _CommandRunSolver())

View File

@@ -49,5 +49,4 @@ class _CommandShellThickness(FemCommands):
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemShellThickness.makeFemShellThickness()]")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_ShellThickness', _CommandShellThickness())
FreeCADGui.addCommand('Fem_ShellThickness', _CommandShellThickness())

View File

@@ -27,7 +27,6 @@ __url__ = "http://www.freecadweb.org"
## @package CommandShowResult
# \ingroup FEM
import FreeCAD
from FemCommands import FemCommands
import FreeCADGui
from PySide import QtCore, QtGui
@@ -69,5 +68,5 @@ def get_results_object(sel):
return i
return None
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_ShowResult', _CommandShowResult())
FreeCADGui.addCommand('Fem_ShowResult', _CommandShowResult())

View File

@@ -58,5 +58,5 @@ class _CommandSolverCalculix(FemCommands):
else:
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemSolverCalculix.makeFemSolverCalculix()]")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_SolverCalculix', _CommandSolverCalculix())
FreeCADGui.addCommand('Fem_SolverCalculix', _CommandSolverCalculix())

View File

@@ -49,5 +49,4 @@ class _CommandSolverZ88(FemCommands):
FreeCADGui.doCommand("FemGui.getActiveAnalysis().Member = FemGui.getActiveAnalysis().Member + [FemSolverZ88.makeFemSolverZ88()]")
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Fem_SolverZ88', _CommandSolverZ88())
FreeCADGui.addCommand('Fem_SolverZ88', _CommandSolverZ88())

View File

@@ -44,10 +44,10 @@ class _FemMeshGmsh():
obj.addProperty("App::PropertyLink", "Part", "FEM Mesh", "Part object to mesh")
obj.Part = None
obj.addProperty("App::PropertyFloat", "ElementSizeMax", "FEM Mesh Params", "Max mesh element size (0.0 = infinity)")
obj.addProperty("App::PropertyLength", "ElementSizeMax", "FEM Mesh Params", "Max mesh element size (0.0 = infinity)")
obj.ElementSizeMax = 0.0 # will be 1e+22
obj.addProperty("App::PropertyFloat", "ElementSizeMin", "FEM Mesh Params", "Min mesh element size")
obj.addProperty("App::PropertyLength", "ElementSizeMin", "FEM Mesh Params", "Min mesh element size")
obj.ElementSizeMin = 0.0
obj.addProperty("App::PropertyEnumeration", "ElementDimension", "FEM Mesh Params", "Dimension of mesh elements (Auto = according ShapeType of part to mesh)")

View File

@@ -48,8 +48,8 @@ class _TaskPanelFemMeshGmsh:
self.gmsh_runs = False
self.console_message_gmsh = ''
QtCore.QObject.connect(self.form.if_max, QtCore.SIGNAL("valueChanged(double)"), self.max_changed)
QtCore.QObject.connect(self.form.if_min, QtCore.SIGNAL("valueChanged(double)"), self.min_changed)
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.form.cb_order, QtCore.SIGNAL("activated(int)"), self.choose_order)
QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.update_timer_text)
@@ -91,8 +91,8 @@ class _TaskPanelFemMeshGmsh:
def update(self):
'fills the widgets'
self.form.if_max.setText("{} mm".format(self.clmax))
self.form.if_min.setText("{} mm".format(self.clmin))
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)
index_order = self.form.cb_order.findText(self.order)
@@ -111,11 +111,11 @@ class _TaskPanelFemMeshGmsh:
# 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, value):
self.clmax = float(value)
def max_changed(self, base_quantity_value):
self.clmax = base_quantity_value
def min_changed(self, value):
self.clmin = float(value)
def min_changed(self, base_quantity_value):
self.clmin = base_quantity_value
def choose_dimension(self, index):
if index < 0: