You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python结合Gmsh与VTK解决网格不连通问题

问题:Gmsh生成的网格存在不连通问题

我正在开发一个基于有限元法的几何对象网格创建与处理项目,目前支持导入.step格式文件,选取对象区域后生成网格。开发采用Gmsh API与VTK接口,但生成的网格出现了不连通的问题(.step提取的风扇模型中网格不连通)。

以下是我的实现代码:

componentSelected.meshGeometry.append(filter.GetOutput())  # Add the polygon junction object to the component's mesh geometry list
writer = vtk.vtkSTLWriter()  # Create the STL file writing object
writer.SetInputData(filter.GetOutput())  # Set the polygon junction object as the STL file writing object
writer.SetFileName("grid.stl")  # Set the output file name as "grid.stl"
writer.Write()  # Write the output file
gmsh.initialize()  # Initialize Gmsh
gmsh.merge("grid.stl")  # Import the mesh file
gmsh.model.mesh.create_edges()  # Create mesh edges
gmsh.model.mesh.create_faces()  # Create mesh faces
gmsh.model.mesh.create_topology()  # Create mesh topology
gmsh.model.mesh.create_geometry()  # Create mesh geometry
# gmsh.model.addPhysicalGroup(1, [1], 1)  # Define physical group 1 as polygon 1
# gmsh.model.geo.add_curve_loop([1], 1)  # Define curve loop 1 as curve 2
gmsh.model.occ.synchronize()  # Synchronize geometry
gmsh.model.geo.synchronize()  # Synchronize geometry
if meshType == 6:
    # If the mesh type is triangular
    gmsh.option.set_number('Mesh.Algorithm', meshType)  # Set the mesh type to triangular
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0)  # Set the minimum mesh size
    gmsh.option.setNumber('Mesh.MeshSizeMax', 1)  # Set the maximum mesh size
elif meshType == 8:
    # If the mesh type is quadrangular
    gmsh.option.setNumber('Mesh.Algorithm', meshType)  # Set the mesh type to quadrangular
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0)  # Set the minimum mesh size
    gmsh.option.setNumber('Mesh.MeshSizeMax', 1)  # Set the maximum mesh size
    gmsh.option.setNumber('Mesh.RecombineAll', 1)  # Set recombination of all meshes to true
    gmsh.option.setNumber('Mesh.RecombinationAlgorithm', 3)  # Set the mesh recombination algorithm to "blossom full-quad"
    gmsh.option.setNumber("Mesh.SubdivisionAlgorithm", 1)  # Set the mesh subdivision algorithm to "all quadrangles"
gmsh.model.geo.synchronize()  # Synchronize geometry
gmsh.model.mesh.generate(2)  # Generate the mesh
gmsh.write("mesh.vtk")  # Write the mesh in VTK format
gmsh.finalize()  # Finalize Gmsh

reader = vtk.vtkDataSetReader()  # Create the VTK file reading object
reader.SetFileName("mesh.vtk")  # Set the input file name as "mesh.vtk"
reader.Update()  # Update the VTK file reading object
grid = reader.GetOutput()  # Set the VTK file reading object as the mesh object
filter = vtk.vtkUnstructuredGridGeometryFilter()  # Create the unstructured mesh geometry filtering object
filter.SetInputData(grid)  # Set the mesh object as the unstructured mesh geometry filtering object
filter.Update()  # Update the unstructured mesh geometry filtering object
edges = vtk.vtkExtractEdges()  # Create the edges extraction object
edges.SetInputConnection(filter.GetOutputPort())  # Set the unstructured mesh geometry filtering object as the edges extraction object
edges.Update()  # Update the edges extraction object
try:
    componentSelected.meshGeometry[main.selectedId] = grid  # Set the mesh object as the component's mesh geometry
    mapper = vtk.vtkDataSetMapper()  # Create the mesh data mapping object
    mapper.SetInputData(edges.GetOutput())  # Set the edges extraction object as the mesh data mapping object
    mapper2 = vtk.vtkDataSetMapper()  # Create the mesh data mapping object
    mapper2.SetInputData(grid)  # Set the mesh object as the mesh data mapping object
    actor = vtk.vtkActor()  # Create the actor object
    actor.SetMapper(mapper)  # Set the mesh data mapping object as the actor object
    actor.GetProperty().SetColor(0, 0, 0)  # Set the color of the actor object to black
    actor.GetProperty().SetInterpolationToFlat()
    actor.GetProperty().EdgeVisibilityOn()  # Set the visibility of the actor's edges to true
    actor2 = vtk.vtkActor()  # Create the actor object
    actor2.SetMapper(mapper2)  # Set the mesh data mapping object as the actor object
    actor2.GetProperty().SetInterpolationToFlat()
    actor2.GetProperty().SetColor(componentSelected.redColor, componentSelected.greenColor, componentSelected.blueColor)  # Set the color of the actor object to the component's color
    componentSelected.meshActor.append(actor)  # Add the actor object to the list of component mesh actors
    componentSelected.geometryMeshActor.append(actor2)  # Add the actor object to the list of component geometry mesh actors
    main.ren.AddActor(actor)  # Add the actor object to the scene
    main.componentId = None  # Set the component identifier to null
    main.selectedId += 1  # Increment the selection identifier
    # Add the mesh to the scene
    for actor in componentSelected.meshActor:
        main.ren.AddActor(actor)
    main.vtkWidget.GetRenderWindow().Render()
    main.selectedComponents.clear()  # Clear the list of selected components
    main.selectedCells.clear()  # Clear the list of selected cells
    return
except Exception as error:
    # If the mesh is not generated
    message = QtGui.QMessageBox()
    message.setText(f"error: {error}")
    message.exec()
    return

解决方案

针对网格不连通的问题,可以从以下几个关键环节修复:

1. 修复STL导入后的几何拓扑缺陷

STL格式本身不带拓扑信息,导入Gmsh后容易出现点重合、面间隙等问题,直接导致网格断裂。添加以下修复步骤:

# 导入STL后立即添加几何修复
gmsh.option.setNumber('Geometry.Tolerance', 1e-6)  # 设置容差,合并距离极近的点
gmsh.model.mesh.removeDuplicateNodes()  # 清除重复节点
gmsh.model.mesh.removeDuplicateElements()  # 清除重复单元
gmsh.model.occ.healShapes()  # 自动修复几何形状的拓扑问题
gmsh.model.occ.synchronize()

2. 简化Gmsh拓扑生成流程

你当前代码中create_edges、create_faces等调用属于冗余操作,导入STL后Gmsh已自动生成基础拓扑,这些调用反而可能破坏原有结构,直接删除即可。

3. 修正网格尺寸参数

设置Mesh.MeshSizeMin = 0会导致Gmsh在局部生成极小网格,引发拓扑断裂。根据模型实际尺寸设置合理的最小网格尺寸:

gmsh.option.setNumber('Mesh.MeshSizeMin', 0.1)  # 示例值,需根据模型大小调整
gmsh.option.setNumber('Mesh.MeshSizeMax', 1)

4. 修改后的完整核心代码片段

componentSelected.meshGeometry.append(filter.GetOutput())
writer = vtk.vtkSTLWriter()
writer.SetInputData(filter.GetOutput())
writer.SetFileName("grid.stl")
writer.Write()

gmsh.initialize()
gmsh.merge("grid.stl")

# 新增几何修复步骤
gmsh.option.setNumber('Geometry.Tolerance', 1e-6)
gmsh.model.mesh.removeDuplicateNodes()
gmsh.model.mesh.removeDuplicateElements()
gmsh.model.occ.healShapes()
gmsh.model.occ.synchronize()

if meshType == 6:
    gmsh.option.set_number('Mesh.Algorithm', meshType)
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0.1)
    gmsh.option.setNumber('Mesh.MeshSizeMax', 1)
elif meshType == 8:
    gmsh.option.setNumber('Mesh.Algorithm', meshType)
    gmsh.option.setNumber('Mesh.MeshSizeMin', 0.1)
    gmsh.option.setNumber('Mesh.MeshSizeMax', 1)
    gmsh.option.setNumber('Mesh.RecombineAll', 1)
    gmsh.option.setNumber('Mesh.RecombinationAlgorithm', 3)
    gmsh.option.setNumber("Mesh.SubdivisionAlgorithm", 1)

gmsh.model.mesh.generate(2)
gmsh.write("mesh.vtk")
gmsh.finalize()

# 后续VTK渲染代码保持不变

内容的提问来源于stack exchange,提问作者lucasteix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:45:54