许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  用Python脚本实现HyperMesh四面体抽壳操作

用Python脚本实现HyperMesh四面体抽壳操作

阅读数 2
点赞 0
article_banner

本人最近遇到一个问题,要对Hypermesh中的四面体抽壳,所以用Python做了一个四面体抽壳的工具,写博客记录一下。

首先在Hypermesh中导出K文件,接下来的所有操作都是基于K文件进行的,Hypermesh导出K文件如下图:

Hypermesh导入K文件如下图:

第一步,逐行读取K文件,识别K文件中的单元类型。

       一般情况下K文件含有2种二维单元(shell):三角形和四边形;含有3种三维单元(solid):四面体,六面体,八面体。

from itertools import combinationsimport refrom ToolBox import My_write,My_deletfile,My_recgnize,My_f_write,Find_max_IDdef read_k_file(filename):    i = 1    shell_num = 0    solid_num = 0    pp = ""    with open(filename,"r") as F:        while True:            Line=F.readline()            if Line:                pp = pp + Line                if "*ELEMENT_SHELL" in Line:                    shell_num=shell_num+1                elif "*ELEMENT_SOLID" in Line:                    solid_num=solid_num+1            else:                break    return pp,shell_num,solid_num#pp是K文件全部内容,shell_num是shell数量,solid_num是solid数量

函数返回值为包含整个K文件的 字符串  ,shell数量和solid数量,用于判断文件中书否含有待处理的四面体

第二步,分割K文件

       将K文件分割为几部分:

              文件头(head),文件尾(button),根据具体情况将具体单元信息分割为几部分(shell_3,shell_4;solid_4,solid_6,

solid_8),分别存入几个文件中,以待后用

def split_file(pp,shell_num,solid_num):    My_deletfile("shell_3.k")    My_deletfile("shell_4.k")    My_deletfile("shell_temp.k")    My_deletfile("solid_4.k")    My_deletfile("solid_6.k")    My_deletfile("solid_8.k")    My_deletfile("solid_temp1.k")    My_deletfile("solid_temp2.k")    My_deletfile("solid_temp3.k")    #首先清除所有中间文件    if shell_num:        head = re.compile(r'(.*?)\n\*ELEMENT_SHELL.*?END', re.S)        My_write(head,pp,"head.k")        #提取文件头        if shell_num==2:            #如果shell_num=2,说明K文件中有全部两种shell单元,三角形在前,四边形在后,依次输出即可            shell_3 = re.compile(r'\*ELEMENT_SHELL\n(.*?)\n\*ELEMENT_SHELL.*?END', re.S)            My_write(shell_3,pp,"shell_3.k")            print("三角形输出完毕")            shell_4 = re.compile(r'\*ELEMENT_SHELL.*?\*ELEMENT_SHELL\n(.*?)\n\*.*?END', re.S)            My_write(shell_4,pp,"shell_4.k")            print("四边形输出完毕")        elif shell_num==1:            #如果shell_num=1,说明只有一种shell单元,可能是三角形,也可能是四面体,这时需要先写入到临时文件中进一步判断            shell_temp = re.compile(r'\*ELEMENT_SHELL\n(.*?)\n\*.*?END', re.S)            My_write(shell_temp, pp, "shell_temp.k")            My_recgnize("shell_temp.k")#进一步判断单元类型    else:        #shell_num=0,即没有面单元,如果有体单元,则头文件为*ELEMENT_SOILD之前的部分;如果也没有体单元,则输出警告        if solid_num:            head = re.compile(r'(.*?)\n\*ELEMENT_SOLID.*?END', re.S)            My_write(head, pp, "head.k")        else:            print("没有体单元,也没有面单元")    if solid_num:        if solid_num==3:            #如果文件中含全部三种体单元,按四面体,六面体,八面体的顺序输出即可,否则需要先写入临时文件,进一步判断            solid_4=re.compile(r'\*ELEMENT_SOLID\n(.*?)\n\*ELEMENT_SOLID.*?\*ELEMENT_SOLID.*?\*.*?END',re.S)            My_write(solid_4,pp,"solid_4.k")            print("四面体输出完毕")            solid_6 = re.compile(r'\*ELEMENT_SOLID\n.*?\n\*ELEMENT_SOLID\n(.*?)\n\*ELEMENT_SOLID.*?\*.*?END', re.S)            My_write(solid_6, pp, "solid_6.k")            print("六面体输出完毕")            solid_8 = re.compile(r'\*ELEMENT_SOLID\n.*?\n\*ELEMENT_SOLID.*?\*ELEMENT_SOLID\n(.*?)\n\*.*?END', re.S)            My_write(solid_8, pp, "solid_8.k")            print("八面体输出完毕")            button = re.compile(r'\*ELEMENT_SOLID.*?\*ELEMENT_SOLID.*?\*ELEMENT_SOLID.*?(\*.*?END)', re.S)            My_write(button,pp,"button.k")        elif solid_num==2:            solid_temp1 = re.compile(r'\*ELEMENT_SOLID\n(.*?)\n\*ELEMENT_SOLID.*?\*.*?END', re.S)            My_write(solid_temp1, pp, "solid_temp1.k")            My_recgnize("solid_temp1.k")            solid_temp2 = re.compile(r'\*ELEMENT_SOLID.*?\*ELEMENT_SOLID\n(.*?)\n\*.*?END', re.S)            My_write(solid_temp2, pp, "solid_temp2.k")            My_recgnize("solid_temp2.k")            button = re.compile(r'\*ELEMENT_SOLID.*?\*ELEMENT_SOLID.*?(\*.*?END)', re.S)            My_write(button, pp, "button.k")        elif solid_num==1:            solid_temp3 = re.compile(r'\*ELEMENT_SOLID\n(.*?)\n\*.*?END', re.S)            My_write(solid_temp3, pp, "solid_temp3.k")            My_recgnize("solid_temp3.k")            button = re.compile(r'\*ELEMENT_SOLID.*?(\*.*?END)', re.S)            My_write(button, pp, "button.k")    else:        print("没有体单元")

用到的函数:

#删除文件函数def My_deletfile(filename):    if os.path.exists(filename):        # 删除文件,可使用以下两种方法。        os.remove(filename)        # os.unlink(my_file)        print("成功删除文件:%s" %filename)    else:        print('不存在文件:%s' % filename)
#进一步判断单元类型def My_recgnize(filename):    with open(filename,"r",encoding="utf-8") as f:        Line=f.readline()        lline=Line.split()        print(lline)        content = f.read()        if len(lline)==6:            if lline[5]==lline[4]:                with open("shell_3.k","w",encoding="utf-8")as F :                    F.write(content)                print("三角形输出完毕")            elif lline[4]!=lline[5]:                with open("shell_4.k","w",encoding="utf-8")as F :                    F.write(content)                print("四边形输出完毕")            else:                print("都不是")        if len(lline)==10:            if lline[8]==lline[6]==lline[7]:                with open("solid_4.k", "w", encoding="utf-8")as F:                    F.write(content)                print("四面体输出完毕")            elif lline[7]==lline[6] and lline[8]!=lline[7]:                with open("solid_6.k", "w", encoding="utf-8")as F:                    F.write(content)                print("六面体输出完毕")            else:                with open("solid_8.k", "w", encoding="utf-8")as F:                    F.write(content)                print("八面体输出完毕")

第三步,四面体抽壳和重新封装K文件

       首先选择文件保存目录,并将头文件先存入目标文件。

       如果原文件含三角形,则先写入,然后对四面体抽壳并将结果写入目标文件;如果没三角形,则直接将四面体抽壳的结果写入。

       四面体抽壳:

               逐行读取第二步中得到的solid_4文件,数据格式如下:

               3177856    2009 3093371 3080613 3093375 3080578 3080578 3080578 3080578 3080578

               共10列数据,每列8位,其中第一列为单元ID,第二行为componentID,3~10列为组成单元的8个NodeID。我们可以看到四面体的第5~8个NodeID相同,因此取1~4个NodeID进行排列组合。

         之后将其他单元和文件尾按顺序写入即可

重组主函数:

def Reorder(filename):    My_deletfile(filename)    with open(filename,"a",encoding="utf-8") as f:        Write_orign("head.k",f)        Write_orign("shell_3.k",f)        Write_orign("shell_4.k", f)        Write_orign("solid_4.k", f)        Write_orign("solid_6.k", f)        Write_orign("solid_8.k", f)        Write_orign("button.k", f)

写入文件函数:

def Write_orign(filename,f):    try:        with open(filename,"r",encoding="utf-8") as Orign:            if filename == "shell_3.k":                f.write("*ELEMENT_SHELL"+"\n")                solid2shell(f)            elif  filename == "shell_4.k":                f.write("*ELEMENT_SHELL" + "\n")            elif filename == "solid_4.k" or filename == "solid_6.k" or filename == "solid_8.k":                f.write("*ELEMENT_SOLID"+"\n")            f.write(Orign.read()+"\n")    except:        if filename=="shell_3.k":            f.write("*ELEMENT_SHELL"+"\n")            solid2shell(f)        print("文件%s" %filename+"不存在")

四面体抽壳函数:

def solid2shell(f):    MAX_ID=max(Find_max_ID("shell_3.k",0),Find_max_ID("shell_4.k",0),Find_max_ID("solid_4.k",0),               Find_max_ID("solid_6.k",0),Find_max_ID("solid_8.k",0))    MAX_comp_ID = max(Find_max_ID("shell_3.k", 1), Find_max_ID("shell_4.k", 1), Find_max_ID("solid_4.k", 1),                 Find_max_ID("solid_6.k", 1), Find_max_ID("solid_8.k", 1))    with open("solid_4.k",'r') as solid:        k = 1        while True:            line = solid.readline()            if line:                line1=line.split()                sort=list(combinations(line1[2:6],3))                for i in range(len(sort)):                    My_f_write(MAX_ID+k,f)                    k = k + 1                    My_f_write(MAX_comp_ID+1,f)                    for j in range(len(sort[0])):                        My_f_write(int(sort[i][j]),f)                    My_f_write(sort[i][2]+"\n",f)            else:                break

寻找最大partID和conponentID函数:

def Find_max_ID(filename,num):    try:        with open(filename,"r",encoding="utf-8") as f:            ID=[0,0]            while True:                line=f.readline()                if line:                    Line=line.split()                    try:                        ID[0]=int(Line[num])                        if ID[0]>ID[1]:                            ID[1]=ID[0]                    except:                        continue                else:                    break        return ID[1]    except:        return 0

按8位格式将数据写入文件函数:

 def My_f_write(A,f):    if  int(A)>= 0 and int(A)< 10:        f.write(" " * 7 + str(A))    if int(A) >= 10 and int(A) < 100:        f.write(" " * 6 + str(A))    if int(A) >= 100 and int(A) < 1000:        f.write(" " * 5 + str(A))    if int(A) >= 1000 and int(A) < 10000:        f.write(" " * 4 + str(A))    if int(A) >= 10000 and int(A) < 100000:        f.write(" " * 3 + str(A))    if int(A) >= 100000 and int(A) < 1000000:        f.write(" " * 2 + str(A))    if int(A) >= 1000000 and int(A) < 10000000:        f.write(" " * 1 + str(A))    if int(A) >= 10000000 and int(A) < 100000000:        f.write(str(A))

第五步,制作UI

为了给程序加上UI,我使用了PyQt5库。同时还对前文中的一些函数做了更改,但基本的原理没有改变,更改的目的只是让UI更人性化。UI程序如下:

import sysfrom PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication,QFileDialog,QMessageBox,QLineEdit,QLabelfrom Read_K_File import read_k_file,split_file,Reorderfrom PyQt5.QtGui import QIcon,QPixmap,QGuiApplicationfrom random import randintfrom time import clock,sleepfrom ToolBox import My_deletfile class Example(QMainWindow):     def __init__(self):        super().__init__()        self.pp = ""        self.shell_num = 0        self.solid_num = 0        self.initUI()     def initUI(self):        self.inputfile_name = QLineEdit(self)        self.inputfile_name.move(220, 438)        self.inputfile_name.resize(760, 40)         self.outputfile_name = QLineEdit(self)        self.outputfile_name.move(220, 498)        self.outputfile_name.resize(760, 40)         #lable_2=QLabel()        #lable_2.setGeometry(100,500,100,100)        #lable_2.setPixmap(QPixmap("https://www.gofarlic.com\document\Python\GUIdesign\Boom.jpg"))         self.lb1 = QLabel(self)        self.lb1.setGeometry(20, 20, 225, 400)        self.lb2 = QLabel(self)        self.lb2.setGeometry(20+225+20, 20, 225, 400)        self.lb3 = QLabel(self)        self.lb3.setGeometry(20+225+20+225+20, 20, 225, 400)        self.lb4 = QLabel(self)        self.lb4.setGeometry(20+225+20+225+20+225+20, 20, 225, 400)        self.create_fignum()         btn1 = QPushButton("选择待处理K文件", self)        btn1.move(20, 438)        btn1.resize(180,40)         btn2 = QPushButton("选择K文件保存目录", self)        btn2.move(20, 498)        btn2.resize(180,40)         btn3 = QPushButton("第一步:读取K文件", self)        btn3.move(20, 558)        btn3.resize(300,40)         btn4 = QPushButton("第二步:分割K文件", self)        btn4.move(350, 558)        btn4.resize(300, 40)         btn5=QPushButton("第三步:四面体抽壳&&&重组K文件",self)        btn5.move(680,558)        btn5.resize(300, 40)         btn1.clicked.connect(self.buttonClicked)        btn2.clicked.connect(self.buttonClicked)        btn3.clicked.connect(self.Read_K_file)        btn4.clicked.connect(self.Split_K_file)        btn5.clicked.connect(self.Reorder)         self.setGeometry(300, 300, 1000,618 )        self.setWindowTitle('四面体抽壳小程序')        self.setWindowIcon(QIcon("img\Boom.jpg"))        self.show()        self.setFixedSize(self.width(), self.height())        self.gui = QGuiApplication.processEvents     def create_fignum(self):        fig_num = [randint(1, 28)]        while True:            if len(fig_num) <4:                K = randint(1, 28)                if K in fig_num:                    continue                else:                    fig_num.append(K)            else:                break        self.lb1.setPixmap(QPixmap("img/" + str(fig_num[0]) + "_1.jpg"))        self.lb2.setPixmap(QPixmap("img/" + str(fig_num[1]) + "_1.jpg"))        self.lb3.setPixmap(QPixmap("img/" + str(fig_num[2]) + "_1.jpg"))        self.lb4.setPixmap(QPixmap("img/" + str(fig_num[3]) + "_1.jpg"))     def buttonClicked(self):        sender = self.sender()        if sender.text()=="选择待处理K文件":            fileName1, filetype = QFileDialog.getOpenFileName(self,                                                              "选取文件",                                                              sys.path[0],                                                              "K文件(*.k);;txt文件 (*.txt);;所有文件 (*)")            self.statusBar().showMessage(fileName1)            self.inputfile_name.setText(fileName1)        elif sender.text()=="选择K文件保存目录":            self.statusBar().showMessage(sender.text() + ' was pressed')            fileName2, filetype = QFileDialog.getSaveFileName(self,                                                              "选取文件",                                                              sys.path[0],                                                              "K文件(*.k);;txt文件 (*.txt);;所有文件 (*)")            self.statusBar().showMessage(fileName2)            self.outputfile_name.setText(fileName2)    def Read_K_file(self):        if self.inputfile_name.text():            with open(self.inputfile_name.text(),"r") as F:                start=clock()                i=1                line_num=1                pp=''                while True:                    self.statusBar().showMessage("开始读取K文件,如有卡顿属于正常现象,稍等即可,不用退出。已读取 "+str(line_num)+" 行")                    line_num = line_num + 1                    Line = F.readline()                    if Line:                        pp = pp + Line                        if "*ELEMENT_SHELL" in Line:                            self.shell_num=self.shell_num+1                        elif "*ELEMENT_SOLID" in Line:                            self.solid_num=self.solid_num+1                        elif "*END" in Line:                            self.pp = self.pp + pp                    else:                        break                    if i == 20000:                        self.pp=self.pp+pp                        pp=''                        self.gui()                        sleep(0.5)                        self.create_fignum()                        i=0                    i=i+1                endd=clock()                self.statusBar().showMessage("共读取 "+str(line_num)+" 行数据,用时:"+str(endd-start)+"秒")            Message="读取K文件完毕!"+"\n"+"共有"+str(self.shell_num)+"种面单元;有"+str(self.solid_num)+"种体单元"            QMessageBox.information(self,"Information",Message,QMessageBox.Yes)        else:            self.Message("请选择待处理K文件!")    def Split_K_file(self):        self.statusBar().showMessage("开始分割K文件")        if self.pp:            split_file(self.pp, self.shell_num, self.solid_num,self.statusBar().showMessage,self.Message)            Message="分割K文件完成!"            QMessageBox.information(self, "Information", Message, QMessageBox.Yes)        else:            self.Message("没有读取文件")    def Reorder(self):        try:            with open("head.k","r") as f:                self.statusBar().showMessage("开始抽壳和重组文件,依然会有失去响应的现象,请少安勿燥")                if self.outputfile_name.text():                    Reorder(self.outputfile_name.text(),self.statusBar().showMessage,self.Message,self.create_fignum,self.gui)                    Message = "抽壳和重组文件完成!"                    QMessageBox.information(self, "Information", Message, QMessageBox.Yes)                else:                    self.Message("没选择K文件保存目录")        except:            self.Message("还没有分割K文件!!!")        My_deletfile("shell_3.k")        My_deletfile("shell_4.k")        My_deletfile("shell_temp.k")        My_deletfile("solid_4.k")        My_deletfile("solid_6.k")        My_deletfile("solid_8.k")        My_deletfile("solid_temp1.k")        My_deletfile("solid_temp2.k")        My_deletfile("solid_temp3.k")        My_deletfile("head.k")        My_deletfile("button.k")    def Message(self,message):        reply=QMessageBox.warning(self,"警告",message,QMessageBox.Yes)   if __name__ == '__main__':    app = QApplication(sys.argv)    ex = Example()    sys.exit(app.exec_())

UI中包含了按钮,文本框,图片等元素,都比较简单,有不明白的朋友自行百度即可

第六部,制作exe文件

终于到了最后一步,打包Exe文件,让这个程序运行在没有python的环境下,为此我们需要安装pyinstaller库,这个库直接pip安装就好,这里不再介绍。封装的命令为:pyinstaller  -w solid2shell.py,封装后得到一个文件夹,里面有各种dll文件,我们只需要运行solid2shell.exe文件即可。

放一张打包后的文件截图:

其中除了img文件夹都是直接生成的

最后放一张成品截图:

上面的图片知识装饰,没其他作用。

好了,就是这么多了,有需要源代码或者程序的朋友可以私信我


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删


相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空