python gmesh剖分step、stl模型

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()


你可能感兴趣的:(python,gmesh,python)