1. 程式人生 > 其它 >python gmesh剖分step、stl模型

python gmesh剖分step、stl模型

技術標籤:pythongmeshpython

1.gmsh配置

首先需要安裝gmsh庫,但是用pip有時候會安裝不上,比如一直顯示在安裝卡死等等,可以參考這篇部落格進行本地安裝。

gmsh python配置

就是將gmsh安裝包下載下來,用7z之類的軟體解壓完後,註釋steup.py中下載gmesh軟體的程式碼,然後自己手動下載gmesh軟體的壓縮包,放在gmsh解壓目錄下再進行安裝即可。

2.剖分

首先STEP與STL檔案的模型工藝是完全不一樣的,STEP記錄了模型的各種組成部分,是用來網格剖分比較良好的格式,而STL檔案實際只是記錄了大量的三角面資訊,所以剖分時也只是對三角面進行進一步剖分,所以如果原本STL的模型就不是很好,那麼剖分後也不會好到哪裡去。

所以STEP能影響網格剖分質量的引數有兩個:

  1. MeshSizeFactor:網格大小因素,值越小一個模型剖分的網格也越多越小。
  2. MeshSizeFromCurvature:根據曲率決定網格大小,每2pi弧度剖分n個網格,簡單理解就是這個n設定的越大,曲面上剖分的網格也越多。

STL影響網格剖分質量的有一個:

  1. MathEval:這個不是很懂,但是測試發現無論stl檔案原本什麼樣,MathEval同一個值的時候,網格數量都基本一致,可以理解為是一個規模,越小網格越多。
import math
import os

import gmsh
import numpy as np
import time
import argparse

parser = argparse.ArgumentParser(description='用於網格剖分的命令列工具')
parser.add_argument('path',type=str,help="指定step或stl檔案")
parser.add_argument('-o','--out',type=str,default="out.npy",help="輸出指定路徑")
parser.add_argument('-s','--size',type=float,default=0.05,help="step使用,網格剖分的密度,越小越密")
parser.add_argument('-n','--num',type=int,default=3,help="step使用,每2pi弧度剖分n個網格")
parser.add_argument('-t','--target',type=str,default="3",help="stl使用,將三角形分割至目標程度,2-3大致與剖分密度0.05相同")
parser.add_argument('-g',help="是否顯示模型",action="store_true")

args = parser.parse_args()
path = args.path
if not os.path.exists(path):
    raise Exception("指定檔案錯誤")

start = time.time()

gmsh.initialize()

# step部分
if os.path.splitext(path)[1].lower() == ".step":
    gmsh.open(path)
    gmsh.option.setNumber('Mesh.MeshSizeFactor',args.size)
    gmsh.option.setNumber('Mesh.MeshSizeFromCurvature',args.num)

# stl部分,大概就是重新構建一個模型進行剖分
elif os.path.splitext(path)[1].lower() == ".stl":
    gmsh.merge(path)
    angle = 40
    forceParametrizablePatches = False
    includeBoundary = True

    curveAngle = 180

    gmsh.model.mesh.classifySurfaces(angle * math.pi / 180., includeBoundary,
                                     forceParametrizablePatches,
                                     curveAngle * math.pi / 180.)

    gmsh.model.mesh.createGeometry()

    s = gmsh.model.getEntities(2)
    l = gmsh.model.geo.addSurfaceLoop([s[i][1] for i in range(len(s))])
    gmsh.model.geo.addVolume([l])

    gmsh.model.geo.synchronize()

    funny = False
    f = gmsh.model.mesh.field.add("MathEval")
    if funny:
        gmsh.model.mesh.field.setString(f, "F", "2*Sin((x+y)/5) + 3")
    else:
        # 2-3大概是step0.05的程度
        gmsh.model.mesh.field.setString(f, "F", args.target)
    gmsh.model.mesh.field.setAsBackgroundMesh(f)
else:
    raise Exception("不支援的格式")

# 生成模型,並取得點
gmsh.model.mesh.generate(3)
_, coord, _ = gmsh.model.mesh.getNodes()
# 直接轉換成n行3列的形式
array = coord.reshape((-1,3))
np.save(args.out,array)

# 啟動gui顯示模型
if args.g:
    gmsh.fltk.run()

gmsh.finalize()

elapsed = (time.time()-start)
print("耗時:{}".format(elapsed))

順便附上matplotlib顯示模型的程式碼:

import  numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import warnings

warnings.simplefilter(action="ignore", category=FutureWarning)
warnings.simplefilter(action="ignore", category=UserWarning)

if __name__ == '__main__':
    buf = np.load(r"D:\wyman\proj\echartDemo\gmeshNpy1.npy")

    fig = plt.figure()
    ax = Axes3D(fig)

    # print(buf)

    x = buf[0:,0]
    y = buf[0:,1]
    z = buf[0:,2]

    ax.set_zlabel("Z")
    ax.set_ylabel("Y")
    ax.set_xlabel("X")
    ax.scatter(x, y, z)
    plt.show()