FEM: FEMMesh2Mesh, add the module to convert the surface of a FEMMesh into a Mesh
This commit is contained in:
parent
9e142fd156
commit
10273687bf
|
@ -116,6 +116,7 @@ SET(FemScripts_SRCS
|
|||
FemInputWriterCcx.py
|
||||
FemInputWriterZ88.py
|
||||
FemMaterialMechanicalNonlinear.py
|
||||
FemMesh2Mesh.py
|
||||
FemMeshGmsh.py
|
||||
FemMeshTools.py
|
||||
FemShellThickness.py
|
||||
|
|
|
@ -45,6 +45,8 @@ INSTALL(
|
|||
|
||||
FemGmshTools.py
|
||||
|
||||
FemMesh2Mesh.py
|
||||
|
||||
FemBeamSection.py
|
||||
_FemBeamSection.py
|
||||
_ViewProviderFemBeamSection.py
|
||||
|
|
222
src/Mod/Fem/FemMesh2Mesh.py
Normal file
222
src/Mod/Fem/FemMesh2Mesh.py
Normal file
|
@ -0,0 +1,222 @@
|
|||
# ***************************************************************************
|
||||
# * *
|
||||
# * 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"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
## @package FwmMesh2Mesh
|
||||
# \ingroup FEM
|
||||
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
import Mesh
|
||||
import time
|
||||
|
||||
|
||||
# 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 makeSimpleMesh(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:
|
||||
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
|
||||
|
||||
if output_mesh:
|
||||
obj = Mesh.Mesh(output_mesh)
|
||||
Mesh.show(obj)
|
||||
end_time = time.clock()
|
||||
print 'Mesh by surface search method: ', end_time - start_time
|
||||
|
||||
'''
|
||||
if output_mesh:
|
||||
obj = Mesh.Mesh(output_mesh)
|
||||
Mesh.show(obj)
|
||||
end_time = time.clock()
|
||||
print 'Faces by surface time: ', end_time - start_time
|
||||
# This creates a mesh from all faces defined in the mesh structure
|
||||
# Some meshes from Gmsh or Netgen seems to contain the surface as a list
|
||||
# of faces.
|
||||
|
||||
start_time = time.clock()
|
||||
output_mesh = []
|
||||
for myFace in myFemMesh.Faces:
|
||||
element_nodes = myFemMesh.getElementNodes(myFace)
|
||||
triangle = [myFemMesh.getNodeById(element_nodes[0]),
|
||||
myFemMesh.getNodeById(element_nodes[1]),
|
||||
myFemMesh.getNodeById(element_nodes[2])]
|
||||
output_mesh.extend(triangle)
|
||||
|
||||
if output_mesh:
|
||||
obj = Mesh.Mesh(output_mesh)
|
||||
Mesh.show(obj)
|
||||
end_time = time.clock()
|
||||
print 'Faces by face already in mesh time: ', end_time - start_time
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
femResult = None
|
||||
input_mesh = None
|
||||
|
||||
for theObject in selection:
|
||||
if hasattr(theObject, "TypeId"):
|
||||
print 'The TypeId: ', theObject.TypeId
|
||||
if hasattr(theObject, "Name"):
|
||||
print 'The Name: ', theObject.Name
|
||||
if hasattr(theObject, "FemMesh"):
|
||||
input_mesh = theObject.FemMesh
|
||||
if theObject.TypeId == 'Fem::FemResultObject':
|
||||
femResult = theObject # .DisplacementVectors
|
||||
|
||||
if not input_mesh:
|
||||
QtGui.QMessageBox.critical(None, "femmesh2mesh", "FemMesh object has to be selected!")
|
||||
assert selection, "FemMesh object has to be selected!"
|
||||
if input_mesh:
|
||||
makeSimpleMesh(input_mesh, femResult)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user