重新网格化3D三角形表面以获得更好的网格质量

4

我正在使用Marching Cubes算法从一个体积数据中提取二维表面,这里是一个Gyroid。

import numpy as np
from numpy import sin, cos, pi
from skimage import measure
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def gyroid(x, y, z, t):
    return cos(x)*sin(y) + cos(y)*sin(z) + cos(z)*sin(x) - t

lattice_param = 1.0
strut_param = 0.0
resolution = 31j

x, y, z = pi*np.mgrid[-1:1:resolution, -1:1:resolution, -1:1:resolution] * lattice_param
vol = gyroid(x, y, z, strut_param)

verts, faces = measure.marching_cubes(vol, 0, spacing=(0.1, 0.1, 0.1)) # , normals, values

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:, 1], faces, verts[:, 2], cmap='ocean', lw=1)

enter image description here

这一切都很好,但在很多地方网格质量很差。我无法在网格上运行任何有限元分析,因为许多单元/面积的面积接近零或高度扭曲。

enter image description here

有没有一种方法可以重新网格化给定的顶点并确保特定元素面/面度量(例如长宽比),或者强制Marching Cubes执行这样的操作?

只要网格是公平近似的,我不在乎移动顶点。

5个回答

2
一种选择是使用表面网格软件“重新网格化”Marching Cubes输出。基本上,这意味着Marching Cubes三角剖分将作为初始表面定义进行重新三角剖分。
有许多技术可用于实现此目的。以下是几个可能有用的选项(所有C++ / C实现):
  • JIGSAW:一种受限制的前置德劳内算法^^,通常可以构建非常高质量的表面德劳内三角剖分。对于所示对象的类型,我期望它能够良好地工作。在包含的演示中(提供在MATLAB中),有几个例子解决了Marching Cubes输出的重新网格化问题。
  • CGAL:一种受限制的德劳内细化方法,也可以构建表面德劳内三角剖分,但使用与JIGSAW略有不同的算法,并包括CVT类型的网格优化方案。
  • MMG:一组重新网格化/优化策略(据我所知),可以通过迭代应用局部修改来转换(从而改进)初始网格。

^^ 我是 JIGSAW 的作者,所以在这里大肆宣传一下。


2

鼓励提供外部资源的链接,但请添加链接周围的上下文,以便您的同行用户了解它是什么以及为什么存在。始终引用重要链接的最相关部分,以防目标站点无法访问或永久离线。仅包含链接的答案可能会被删除 - Sabito stands with Ukraine
2
其他审阅者请注意,我没有标记此答案。在我看来,“我建议使用带有平滑的三维自适应重网格化”是一个有效的答案。 - Sabito stands with Ukraine

2
我没有足够的声望来发表评论,所以我将其作为答案提交...
在Nico的回答中补充一点,似乎pygalmesh.remesh_surface()的关键参数已经改变。链接中提供的示例是:
mesh = pygalmesh.remesh_surface(
    "lion-head.off",
    max_edge_size_at_feature_edges=0.025,
    min_facet_angle=25,
    max_radius_surface_delaunay_ball=0.1,
    max_facet_distance=0.001,
    verbose=False,
)

此外,meshio.write_points_cells的第三个参数定义了面,而faces必须具有形状(n_faces, 3)以适应三角形元素。在我的情况下,我正在使用来自另一个软件包(PyVista)的不同格式的网格,并且必须重新调整数组的形状。

1

你也可以使用pygalmesh进行表面重网格化。(它是一个易于使用的CGAL接口。)

import pygalmesh

# create verts, faces

meshio.write_points_cells("in.vtu", verts, [("triangle", faces)])

mesh = pygalmesh.remesh_surface(
    "in.vtu",
    edge_size=0.025,
    facet_angle=25,
    facet_size=0.1,
    facet_distance=0.001,
    verbose=False,
)
# mesh.points, mesh.cells

0

奇怪的三角形源于奇怪的数据,而不是用于三角剖分的方法。

我可以说Delaunay三角剖分实现了最佳的三角形面积/周长比(理论上等边三角形具有最佳比例)。但你不能在网格中使用它,因为Delaunay三角剖分输出的是凸网格。

你要完成一项紧迫的任务。以下是一些想法:

  • 在生成网格之前,请删除几乎重复的点。这将避免许多几乎为零的三角形。
  • 检测细长的三角形。将它们细分成更“正常”的三角形。
  • 你可以创建一个密集的规则网格。每个z可以通过遍历网格直到找到包含网格点的x,y坐标的三角形,然后插值z来找到。如果你有一些额外信息,如邻居或层次关系,则可以通过比检查每个三角形更快地进行搜索。对网格进行三角剖分非常简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接