VTK 模型封闭 closeSurface 补洞, 网格封闭性检测

网格封闭性检测 见:

vtk Edges 特征边 提取 网格封闭性检测_vtkfeatureedges-CSDN博客

由于以前做过3D打印模型,要求模型必须是封闭的,原来对模型封闭有研究过,不过没有记录;现在又遇到,整理一下;

1.vtkStripper ,vtkFillHolesFilter

closeSurface  大家首先想到的是 vtkFillHolesFilter

但不一定,由时一个模型是有多个模型组合的,没有连接性,所以首先可以使用:

vtkStripper

见:vtkStripper vtkTriangleFilter-CSDN博客

将多个模型变成一个;

然后使用 vtkFillHolesFilter

  vtkNew<vtkFillHolesFilter> fillHolesFilter;
  fillHolesFilter->SetInputData(polydata);
  fillHolesFilter->SetHoleSize(10.0);
  fillHolesFilter->Update();

2.使用 vtkFillHolesFilter 后,仍然不是闭合

2.1孔洞阈值过小
vtkFillHolesFilter 有一个属性叫做 HoleSize,表示可以填充的最大孔洞的大小(基于孔洞的边界周长)。

  • 解决方法:尝试增大 HoleSize,以确保较大的孔洞也能被填充

 

  vtkNew<vtkFillHolesFilter> fillHolesFilter;
  fillHolesFilter->SetInputData(polydata);
  fillHolesFilter->SetHoleSize(10.0);
  fillHolesFilter->Update();

2.2 几何结构缺陷
原始的 vtkPolyData 可能存在几何缺陷,比如:

  • 非流形边 (Non-manifold edges)
  • 重叠点 (Duplicate points)
  • 法线方向不一致

这些问题可能会导致孔洞无法被正确识别和填充。

  • 解决方法
    1. 使用 vtkCleanPolyData 清理数据,合并重复点并修复拓扑结构。
    2. 使用 vtkPolyDataNormals 确保法线方向一致。
# 清理PolyData
cleanFilter = vtk.vtkCleanPolyData()
cleanFilter.SetInputData(polydata)
cleanFilter.Update()

# 重新计算法线
normals = vtk.vtkPolyDataNormals()
normals.SetInputData(cleanFilter.GetOutput())
normals.ConsistencyOn()  # 确保法线方向一致
normals.AutoOrientNormalsOn()
normals.Update()

# 填充孔洞
fillHolesFilter = vtk.vtkFillHolesFilter()
fillHolesFilter.SetInputData(normals.GetOutput())
fillHolesFilter.SetHoleSize(1000.0)  # 根据情况调整阈值
fillHolesFilter.Update()

 

2.2 数据孔洞不是封闭边界
如果数据存在不完整的边界或破洞,vtkFillHolesFilter 无法正确填充,因为它只能识别封闭环状的孔洞。

  • 解决方法
    • 使用 vtkDelaunay3D 生成一个闭合的网格。

 

delaunay = vtk.vtkDelaunay3D()
delaunay.SetInputData(polydata)
delaunay.Update()

surfaceFilter = vtk.vtkDataSetSurfaceFilter()
surfaceFilter.SetInputConnection(delaunay.GetOutputPort())
surfaceFilter.Update()

closedPolyData = surfaceFilter.GetOutput()

 使用前,有边界;

 

使用后,无边界:

 不过这个真不是用眼睛能看出来的;需要用算法检测;使用;

vtk Edges 特征边 提取 网格封闭性检测_vtkfeatureedges-CSDN博客

### 使用 VTK网格模型沿顶点进行裁剪 为了实现基于VTK库的网格裁剪功能,可以采用`vtkClipPolyData`类来执行这一操作。此方法允许通过指定隐函数(implicit function),如平面或球体,定义裁剪区域[^1]。 然而,在特定需求下——即依据网格模型的顶点来进行裁剪,则需构建一个能够代表这些顶点位置集合的有效几何形状作为裁剪边界条件。一种常见做法是利用包围盒(bounding box)或者凸包(convex hull),它们能紧密贴合所选顶点群形成最小体积的空间范围。 下面是一个Python脚本实例,展示了如何借助VTK完成上述任务: ```python import vtk def get_convex_hull(points): """计算给定点集对应的凸壳""" convexHull = vtk.vtkDelaunay3D() pointSource = vtk.vtkPoints() for p in points: pointSource.InsertNextPoint(p) polydata = vtk.vtkPolyData() polydata.SetPoints(pointSource) convexHull.SetInputData(polydata) surfaceFilter = vtk.vtkGeometryFilter() surfaceFilter.SetInputConnection(convexHull.GetOutputPort()) surfaceFilter.Update() return surfaceFilter.GetOutput() def clip_mesh_with_vertices(inputMesh, vertexPositions): """ 根据输入的顶点坐标列表对三维模型进行裁剪 参数: inputMesh (vtkPolyData): 待处理的目标网格对象 vertexPositions (list of tuple): 定义裁剪边界的顶点坐标列表 返回值: clippedMesh (vtkPolyData): 裁剪后的网格数据结构 """ # 创建由顶点构成的凸多面体表示形式 clippingRegion = get_convex_hull(vertexPositions) # 将其转换成适合用于裁剪操作的形式 implicitFunction = vtk.vtkImplicitDataSet() implicitFunction.SetDataSet(clippingRegion) # 执行实际的裁剪过程 clipper = vtk.vtkClipPolyData() clipper.SetInputData(inputMesh) clipper.SetClipFunction(implicitFunction) clipper.GenerateClippedOutputOn() # 可选项:保留被裁掉的部分 clipper.SetValue(0) # 默认阈值设置为零 clipper.Update() return clipper.GetOutput() ``` 该代码片段首先定义了一个辅助函数`get_convex_hull()`用来获取一组离散点形成的凸壳;接着实现了核心逻辑`clip_mesh_with_vertices()`接收待裁剪的原始网格以及选定顶点的位置信息,并返回经过裁剪的新网格实体。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋西风

up up up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值