近期本人在学习genesis框架中的fem的求解器,在导入obj文件时,会因为划分网格的问题而报错。(有关genesis的介绍可以看这篇文章,万博总结的非常非常好 GENESIS框架的材料模型-修正剑桥模型的原理与计算方法 ~ web和mechanic技术分享)
报错内容如下:
RuntimeError: Failed to tetrahedralize.
May need to repair surface by making it manifold:
Unknown exception
之后我先是blender中使用3d打印来输出非流形的点和边,如下图所示
在使用了make mainfold这个方法之后,图形变成了这样。
根据上述图片,因为都是相交的地方被移除了,所以大概率是每个立方体之间相接触的部分有问题。之后通过blender看网格文件看出了在相交的地方有共用点。推测在共用点的地方tetgen中对obj文件网格化的过程中,会出现判断不了点的归属问题而导致obj文件四面体化错误。
在查找了资料过后,决定使用布尔差值的方法来重构模型。有两条路可以选择。
一是在genesis库中使用
box = trimesh.creation.box(extents=[5, 18,28])
result_mesh = mesh.difference([box],engine='manifold')
做差值运算
二是在blender中使用修改器来做布尔差值,考虑到可视化,最后使用blender来做。
在重构了模型之后,我记得那天兴致勃勃的导入obj文件,可是还是报错了。我记得那天非常沮丧,以致于早早离开工作所回宿舍里打游戏
第二天在与万博谈论之后,他建议我去通读genesis库中有关导入obj模型时,对obj模型所作的操作,并在没有taichi的环境下进行编译。
import pyvista as pv
import tetgen
def load_obj(file_path):
# 加载 OBJ 文件
mesh = pv.read(file_path)
return mesh
def is_triangles(mesh):
# 检查并将网格三角化
if not mesh.is_all_triangles():
mesh = mesh.triangulate()
return mesh
def ensure_triangulated(mesh):
# 确保网格为三角形
mesh = is_triangles(mesh)
return mesh
def repair_mesh(mesh):
# 修复网格,使其成为流形
if not mesh.is_manifold:
mesh = mesh.clean()
return mesh
def tetrahedralize_mesh(mesh):
# 使用 TetGen 进行四面体化
tet = tetgen.TetGen(mesh)
verts, elems = tet.tetrahedralize()
return verts, elems
def main(file_path):
# 加载并处理网格
mesh = load_obj(file_path)
mesh = ensure_triangulated(mesh)
mesh = repair_mesh(mesh)
verts, elems = tetrahedralize_mesh(mesh)
return verts, elems
# 示例调用
if __name__ == "__main__":
file_path = "/home/robot/文档/Genesis-main/Genesis/genesis/assets/meshes/cube.obj"
verts, elems = main(file_path)
print(f"顶点数: {len(verts)}, 元素数: {len(elems)}")
这部分代码就是genesis库中fem求解器对obj文件的处理流程,并通过检验我之前成功跑通的fem模型验证这串代码的正确性。
之后在报错信息中知道了obj模型要三角化,才能正确在fem求解器中导入
如图所示,将面三角化。
在经历了这么多试错,花费了两周时间才最终把基坑模型给正确导入。
从这两周的学习过程中我学习到
1.在blender中建模型要使用挖空的方法,而不是一个又一个的模型拼凑的方法
2.注重源码,而不是一味尝试
3.修复网格中三角化的重要性
4.将每次万博的指令,记在本子里,并充分谈论,确保指令能落到实处,并且不要拖延
5.之后在写一个有关自动化建模的软件时,可以考虑在genesis库中使用布尔差值(其中需要学习矩阵运算对坐标和角度的影响),或者之间导入blender库
6.在tetgen中可以设计一个算法,去除重复点,但目前对面的影响和相交部分的点没有处理处理思路。想自己以后设计一个算法来解决网格自相交的问题。