用Python对Hypermesh四面体抽壳

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

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

 Hypermesh导入K文件如下图:

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

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

from itertools import combinations
import re
from ToolBox import My_write,My_deletfile,My_recgnize,My_f_write,Find_max_ID
def 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 sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication,QFileDialog,QMessageBox,QLineEdit,QLabel
from Read_K_File import read_k_file,split_file,Reorder
from PyQt5.QtGui import QIcon,QPixmap,QGuiApplication
from random import randint
from time import clock,sleep
from 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("D:\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文件夹都是直接生成的

最后放一张成品截图:

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

 

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章