5.vtk学习——点云显示进阶

三角化模型显示实现

承接上文,这里介绍如何实现点云三角化后的显示效果。

三角化显示效果

如果理解了前文内容,这里的思路就非常自然:三角化会把点相连形成三角面,这些三角面正是我们需要显示的拓扑结构
我们只需从 Halcon 获取三角化后的三角形数据,并添加到 VTK 中作为拓扑结构,即可显示模型。


实现过程

1. 点云预处理与三角化

首先,读取点云数据,生成 3D 模型,然后进行滤波、采样和三角化。

// 读取点云坐标
HOperatorSet.ReadTuple(@"C:\Users\Yty\Desktop\xpoints.dat", out var X);
HOperatorSet.ReadTuple(@"C:\Users\Yty\Desktop\ypoints.dat", out var Y);
HOperatorSet.ReadTuple(@"C:\Users\Yty\Desktop\zpoints.dat", out var Z);

// 生成3D对象
HOperatorSet.GenObjectModel3dFromPoints(X, Y, Z, out var WareModel3D);

// 采样
double SamplingFactor = 0.01;
HOperatorSet.GetObjectModel3dParams(WareModel3D, "diameter_axis_aligned_bounding_box", out var Diameter);
HOperatorSet.SampleObjectModel3d(WareModel3D, "fast", SamplingFactor * Diameter, new HTuple(), new HTuple(), out var SampledWareModel3D);

// 计算法向量
HOperatorSet.SurfaceNormalsObjectModel3d(SampledWareModel3D, "mls", new HTuple(), new HTuple(), out SampledWareModel3D);

// 三角化
HOperatorSet.TriangulateObjectModel3d(SampledWareModel3D, "greedy", new HTuple(), new HTuple(), out var TriangulatedObjectModel3D, out var Information);

// 获取三角形和点坐标
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "triangles", out var tris);
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "point_coord_x", out var hv_x);
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "point_coord_y", out var hv_y);
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "point_coord_z", out var hv_z);
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "num_points", out var hv_num);
HOperatorSet.GetObjectModel3dParams(TriangulatedObjectModel3D, "num_triangles", out var numTris);

说明:每 3 个 tris 元素表示一个三角形的三个顶点索引,例如 [0,10,11] 表示三角形由索引 0、10、11 的点组成。


2. 添加拓扑结构到 VTK

根据 Halcon 的三角化数据,创建 vtkTriangle 并插入 vtkCellArray,然后构建 vtkPolyData

vtkCellArray vtkCell = new vtkCellArray();
for (int i = 0; i < numTris; i++)
{
    vtkTriangle tri = new vtkTriangle();
    tri.GetPointIds().SetNumberOfIds(3);
    tri.GetPointIds().SetId(0, tris[i * 3]);
    tri.GetPointIds().SetId(1, tris[i * 3 + 1]);
    tri.GetPointIds().SetId(2, tris[i * 3 + 2]);
    vtkCell.InsertNextCell(tri);
}

// 构建 PolyData
vtkPolyData Model3D = new vtkPolyData();
vtkPolyData PointData = new vtkPolyData();

Model3D.SetPoints(Points);
Model3D.GetPointData().SetScalars(colors_rgb);
Model3D.SetPolys(vtkCell);

PointData.SetPoints(Points);

3. 可视化显示

使用 vtkPolyDataMappervtkActor 显示三角化模型和点云。

vtkPolyDataMapper Model3DMapper = vtkPolyDataMapper.New();
vtkPolyDataMapper PointsMapper = vtkPolyDataMapper.New();

vtkVertexGlyphFilter glyphFilter = vtkVertexGlyphFilter.New();
glyphFilter.SetInput(PointData);  // 使用 SetInput

Model3DMapper.SetInput(Model3D);
PointsMapper.SetInput(glyphFilter.GetOutput());

vtkActor ModelActor = vtkActor.New();
vtkActor PointActor = vtkActor.New();

ModelActor.SetMapper(Model3DMapper);
PointActor.SetMapper(PointsMapper);

// 设置透明度
ModelActor.GetProperty().SetOpacity(0.5);

vtkRenderer renderer = vtkRenderer.New();
renderer.AddActor(PointActor);
renderer.AddActor(ModelActor);

// 背景设置
renderer.SetBackground(0, 0, 0);
renderer.GradientBackgroundOn();
renderer.SetBackground2(0.8, 0.8, 0.8);

// 深度剥离设置,保证半透明正确显示
renderer.SetUseDepthPeeling(1);
renderer.SetMaximumNumberOfPeels(300);
renderer.SetOcclusionRatio(0.1);

ResetCamera(Model3D);

// 渲染窗口
renderWindow.AddRenderer(renderer);
renderWindow.SetAlphaBitPlanes(1);
renderWindow.Render();
VtkPanel.Invalidate();
Application.DoEvents();

// 强制刷新三部曲
renderWindow.Render();
VtkPanel.Invalidate(true);
Application.DoEvents();

4. 透明显示效果说明

  1. 直接设置 ModelActor.GetProperty().SetOpacity(0.5) 可以实现透明显示,但可能出现透视错乱。
  2. 原因:VTK 默认使用画家算法渲染半透明面,当多个半透明面重叠时顺序判断不准确。
  3. 解决方法:开启 深度剥离 (Depth Peeling) 渲染模式。

深度剥离设置

renderer.SetUseDepthPeeling(1);          // 开启深度剥离
renderer.SetMaximumNumberOfPeels(300);   // 最大剥离层数
renderer.SetOcclusionRatio(0.1);         // 每层遮挡比例
renderWindow.SetAlphaBitPlanes(1);       // 支持 Alpha 通道

渲染流程:

  1. 渲染场景的第一层透明面(最前面)。
  2. “剥掉”该层深度信息。
  3. 渲染下一层透明面,重复上述步骤。
  4. 将所有层按深度从前到后混合,获得正确的透明显示效果。
posted @ 2025-10-18 17:10  Ytytyty  阅读(86)  评论(0)    收藏  举报