Merge pull request #350 from berndhahnebach/bhbdev057
New tool to onvert surface of FEMMeshes to a Mesh
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -45,6 +45,9 @@ INSTALL(
|
||||
|
||||
FemGmshTools.py
|
||||
|
||||
FemMesh2Mesh.py
|
||||
_CommandFEMMesh2Mesh.py
|
||||
|
||||
FemBeamSection.py
|
||||
_FemBeamSection.py
|
||||
_ViewProviderFemBeamSection.py
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
176
src/Mod/Fem/FemMesh2Mesh.py
Normal 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
|
||||
@@ -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>
|
||||
|
||||
153
src/Mod/Fem/Gui/Resources/icons/fem-femmesh-to-mesh.svg
Normal file
153
src/Mod/Fem/Gui/Resources/icons/fem-femmesh-to-mesh.svg
Normal 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 |
@@ -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"
|
||||
|
||||
@@ -49,6 +49,7 @@ class FemWorkbench (Workbench):
|
||||
import _CommandRunSolver
|
||||
import _CommandPurgeResults
|
||||
import _CommandControlSolver
|
||||
import _CommandFEMMesh2Mesh
|
||||
import _CommandMeshGmshFromShape
|
||||
import _CommandMeshNetgenFromShape
|
||||
import _CommandAnalysis
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
80
src/Mod/Fem/_CommandFEMMesh2Mesh.py
Normal file
80
src/Mod/Fem/_CommandFEMMesh2Mesh.py
Normal 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())
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -61,5 +61,4 @@ class _CommandMeshGmshFromShape(FemCommands):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Fem_MeshGmshFromShape', _CommandMeshGmshFromShape())
|
||||
FreeCADGui.addCommand('Fem_MeshGmshFromShape', _CommandMeshGmshFromShape())
|
||||
|
||||
@@ -55,5 +55,4 @@ class _CommandMeshNetgenFromShape(FemCommands):
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('Fem_MeshNetgenFromShape', _CommandMeshNetgenFromShape())
|
||||
FreeCADGui.addCommand('Fem_MeshNetgenFromShape', _CommandMeshNetgenFromShape())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user