.ply
点云或模型数据进行 Elevation 着色并可视化渲染的完整流程前置代码 加载ply文件
vtkNew<vtkPLYReader> reader;
reader->SetFileName(filePath.toStdString().c_str());
reader->Update();
polyData = reader->GetOutput();
// 获取包围盒 (Bounds)
double bounds[6];
_poly_data->GetBounds(bounds);
// 计算模型中心
double center[3] = {
(bounds[0] + bounds[1]) / 2.0,
(bounds[2] + bounds[3]) / 2.0,
(bounds[4] + bounds[5]) / 2.0};
// 将整个模型向反方向移动,使其中心点对齐原点
vtkNew<vtkTransform> transform;
transform->Translate(-center[0], -center[1], -center[2]);
vtkNew<vtkElevationFilter> elevationFilter;
elevationFilter->SetInputConnection(transformFilter->GetOutputPort());
elevationFilter->SetLowPoint(0, 0, bounds[4] - center[2]);
elevationFilter->SetHighPoint(0, 0, bounds[5] - center[2]);
elevationFilter->Update();
vtkElevationFilter
会根据模型每个点在 Z 轴方向的位置 生成一个标量值(类似“高度”)。LowPoint
和 HighPoint
设置了 Z 轴范围,这里用了 bounds[4/5] - center[2]
是因为模型已经被平移到以原点为中心。 // Jet 颜色映射(蓝→青→绿→黄→红)非线性 Jet LUT
vtkNew<vtkLookupTable> colorLookupTable;
colorLookupTable->SetNumberOfTableValues(256);
double scalarRange[2];
elevationFilter->GetOutput()->GetScalarRange(scalarRange);
colorLookupTable->SetRange(scalarRange);
// colorLookupTable->SetRange(-50, 50); // 固定范围,确保色差
for (int i = 0; i < 256; ++i)
{
double t = i / 255.0;
// 非线性调整 t,使得颜色中段更密集,末端压缩
double gamma = 0.7; // 越小,中间越突出(类似 CloudCompare),可尝试 0.6 ~ 0.8
t = std::pow(t, gamma);
// Jet 调色映射(与 CloudCompare 相似的分布)
double r = std::clamp(1.5 - std::abs(4.0 * t - 3.0), 0.0, 1.0);
double g = std::clamp(1.5 - std::abs(4.0 * t - 2.0), 0.0, 1.0);
double b = std::clamp(1.5 - std::abs(4.0 * t - 1.0), 0.0, 1.0);
colorLookupTable->SetTableValue(i, r, g, b);
}
colorLookupTable->Build();
gamma=0.7
进行非线性压缩,使颜色分布更集中在中间(增加色彩层次感)。[-50, 50]
,也就是说,无论模型多高,色差都按这个范围来映射,这是为了防止模型过扁而无法显著看到颜色过渡。auto vertexGlyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
vertexGlyphFilter->AddInputData(elevationFilter->GetOutput());
vertexGlyphFilter->Update();
vtkVertex
),如果省略这一段,纯点云将无法显示。auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(vertexGlyphFilter->GetOutputPort());
mapper->SetScalarRange(elevationFilter->GetOutput()->GetScalarRange());
mapper->SetLookupTable(colorLookupTable);
mapper->SetColorModeToMapScalars();
mapper->ScalarVisibilityOn();
mapper->Update();
SetScalarRange(...)
确保 mapper 知道颜色范围如何对应到颜色表中。ply_point_actor_ = vtkSmartPointer<vtkActor>::New();
ply_point_actor_->SetMapper(mapper);
ply_point_actor_->GetProperty()->SetPointSize(point_size_edit_->text().toInt());
SetPointSize(...)
设置点大小,读取自 UI 控件(point_size_edit_
),用户可调。renderer_->RemoveAllViewProps(); // 移除旧的内容
renderer_->SetBackground(1.0, 1.0, 1.0); // 设置白色背景
renderer_->AddActor(ply_point_actor_); // 添加新Actor
addCoordinateAxes(); // 添加坐标轴
addBoundingBox(transformFilter->GetOutput()); // 添加包围盒
renderer_->ResetCamera(); // 相机重置
renderWindow_->Render(); // 执行渲染
m_pScene->update(); // 通知 UI 更新(Qt)
ResetCamera()
让摄像头自动对准场景。步骤 | 说明 |
---|---|
① ElevationFilter | 为每个点生成 Z 值标量 |
② LookupTable | 创建 Jet 风格 LUT |
③ VertexGlyphFilter | 点 → vtkVertex,确保可渲染 |
④ Mapper | 设置映射、颜色 LUT、标量范围 |
⑤ Actor | 设置点大小、构建可视化对象 |
⑥ Renderer | 清除旧内容、添加新 Actor、刷新界面 |
除了 Jet 风格(蓝→青→绿→黄→红)之外,VTK 和三维可视化中常见的颜色映射表(Lookup Table, LUT)还有以下几类,每种适合不同的可视化目的:
vtkColorTransferFunction::SetColorSpaceToDiverging()
+ 两端色设置vtkLookupTable::SetHueRange(0.0, 1.0);
⚫→⚪ 从黑到白
用途:医学图像、形状对比、打印友好
设置方式:
lut->SetTableValue(i, t, t, t); // R=G=B
vtkColorTransferFunction::SetColorSpaceToRGB()
,然后插值这些颜色vtkUnsignedCharArray
配合使用手动设置几个关键色,插值形成 LUT
用法灵活:地形图、高度图、材质图等
例子:
lut->SetTableValue(0, 0.0, 0.0, 0.5); // 深蓝
lut->SetTableValue(128, 0.0, 1.0, 0.0); // 绿色
lut->SetTableValue(255, 1.0, 1.0, 0.0); // 黄色