如何用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
相关产品推荐
相关产品推荐

