//初始化
void Form_VTK::init()
{
colorFunc = vtkSmartPointer<vtkColorTransferFunction>::New();
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
actor = vtkSmartPointer<vtkActor>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();
scalarBar = vtkSmartPointer<vtkScalarBarActor>::New();
renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
// 输出VTK版本信息(用于调试兼容性问题)
qDebug() << "VTK版本: " << vtkVersion::GetVTKVersion();
//设置UI
vtkWidget = ui->widget; // VTK渲染窗口部件
propertyComboBox = ui->comboBox; // 属性选择下拉框
connect(
propertyComboBox,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), // 显式指定参数类型
this,
&Form_VTK::onPropertyChanged
);
propertyComboBox->setEnabled(false);
initVTKView();
}
//初始化VTK视图
void Form_VTK::initVTKView()
{
}
//加载VTK
void Form_VTK::loadVtkData(QString filePath)
{
bIsInitCompleted = false;
// 读取VTK数据
vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
reader->SetFileName(filePath.toStdString().c_str());
reader->Update();
polyData = reader->GetOutput();
if (polyData->GetNumberOfPoints() == 0) {
qDebug() << "错误:VTK文件无有效数据";
return;
}
// 初始化属性列表(填充下拉框)
vtkPointData* pointData = polyData->GetPointData();
for (int i = 0; i < pointData->GetNumberOfArrays(); i++) {
propertyComboBox->addItem(pointData->GetArrayName(i));
}
setVtkColorFunc(); // 设置属性颜色
bIsInitCompleted = true;
}
//卸载VTK
void Form_VTK::unloadVtkData()
{
// 1. 重置标志位
bIsInitCompleted = false;
// 2. 释放 VTK 数据对象
if (polyData) {
polyData->Initialize(); // 清空数据
polyData = nullptr; // 释放指针
}
// 3. 重置渲染管线组件
if (mapper) {
mapper->RemoveAllInputs(); // 移除输入数据
mapper->SetScalarRange(0, 0); // 重置标量范围
mapper->SetArrayName(nullptr); // 清除数组名
}
if (actor) {
renderer->RemoveActor(actor); // 从渲染器移除actor
actor->SetMapper(nullptr); // 解除与mapper的关联
}
if (colorFunc) {
colorFunc->RemoveAllPoints(); // 清空颜色映射点
colorFunc->Modified(); // 通知管线更新
}
if (scalarBar) {
renderer->RemoveActor2D(scalarBar); // 移除标量条
scalarBar->SetLookupTable(nullptr); // 解除与颜色映射的关联
scalarBar->SetTitle(""); // 清空标题
}
// 4. 重置渲染器和渲染窗口
if (renderer) {
renderer->RemoveActor2D(actor);
renderer->SetBackground(1.0, 1.0, 1.0); // 重置背景色
}
if (renderWindow && vtkWidget) {
renderWindow->Render(); // 刷新渲染窗口(显示空白)
}
// 5. 重置UI控件
propertyComboBox->clear(); // 清空下拉框选项
propertyComboBox->setEnabled(false); // 禁用下拉框
// 6. 输出卸载日志(调试用)
qDebug() << "VTK数据已卸载";
}
//设置属性颜色
void Form_VTK::setVtkColorFunc()
{
// 确保存在有效的PolyData
if (!polyData || polyData->GetNumberOfPoints() == 0) {
qDebug() << "错误:无效的PolyData";
return;
}
// 获取目标数组(使用第一个数组)
vtkPointData* pointData = polyData->GetPointData();
if (!pointData) return;
QString strName = pointData->GetArrayName(0);
vtkDataArray* targetArray = pointData->GetArray(strName.toStdString().c_str());
if (!targetArray)
return;
// 关键步骤:设置活动标量
pointData->SetActiveScalars(targetArray->GetName());
// 获取PointData1的范围(min, max)
double range[2];
targetArray->GetRange(range);
qDebug() << "PointData1 范围: " << range[0] << "到" << range[1];
// 检查是否为有效范围
if (fabs(range[1] - range[0]) < 1e-6) {
qDebug() << "警告:数据范围太小,使用默认范围[-1, 1]";
range[0] = -1.0;
range[1] = 1.0;
}
double minVal = range[0];
double maxVal = range[1];
double midVal = (minVal + maxVal) * 0.5;
qDebug() << "minVal:" << minVal << " midVal:" << midVal << " maxVal:" << maxVal;
// 创建发散色阶(蓝-灰-红)
colorFunc->RemoveAllPoints();
colorFunc->SetColorSpaceToDiverging();
colorFunc->AddRGBPoint(minVal, 0.23, 0.299, 0.754); // 深蓝 (最小值)
colorFunc->AddRGBPoint(midVal, 0.865, 0.865, 0.865); // 中性灰 (中间值)
colorFunc->AddRGBPoint(maxVal, 0.706, 0.016, 0.15); // 深红 (最大值)
colorFunc->Build();
// 配置Mapper
mapper->SetInputData(polyData);
mapper->SetLookupTable(colorFunc);
mapper->SetScalarModeToUsePointData();
mapper->ColorByArrayComponent(strName.toStdString().c_str(), -1);
mapper->SetScalarRange(minVal, maxVal); // 设置完整数据范围
mapper->ScalarVisibilityOn();
mapper->Modified();
// 配置Actor
actor->SetMapper(mapper);
// 配置渲染器
renderer->AddActor(actor);
renderer->SetBackground(1.0, 1.0, 1.0);
//renderer->SetBackground(0.4, 0.4, 0.5); // 浅灰背景(类似ParaView)
renderer->ResetCamera();
//标量条
configureScalarBar(true,strName);
bool visible = scalarBar->GetVisibility();
// 关联渲染窗口
renderWindow->AddRenderer(renderer);
vtkWidget->SetRenderWindow(renderWindow);
renderWindow->Render();
}
//配置标量条
void Form_VTK::configureScalarBar(bool bInit, QString title)
{
//------------------------------------------------------------------------------
if(!bInit)
{
//scalarBar->SetLookupTable(colorFunc);
scalarBar->SetTitle(title.toStdString().c_str());
}
else
{
scalarBar->SetLookupTable(colorFunc);
scalarBar->SetTitle(title.toStdString().c_str());
scalarBar->SetNumberOfLabels(7);
// 解除字体约束
scalarBar->UnconstrainedFontSizeOn();
// 标题字体属性配置
vtkTextProperty* titleProp = scalarBar->GetTitleTextProperty();
titleProp->SetFontSize(16); // 标题字体大小
titleProp->SetFontFamily(VTK_ARIAL);
titleProp->SetColor(1, 1, 200); // 标题颜色
// 标签字体属性配置(保持原有)
vtkTextProperty* labelProp = scalarBar->GetLabelTextProperty();
labelProp->SetFontSize(13); // 标签字体大小
labelProp->SetFontFamily(VTK_ARIAL);
labelProp->SetColor(1, 1, 1); // 标签颜色
// ====== 关键修改:设置标量条宽度和位置 ======
scalarBar->SetOrientationToVertical(); // 确保垂直方向(默认)
scalarBar->SetPosition(0.83, 0.1); // 左下角坐标(归一化坐标系)
scalarBar->SetPosition2(0.05, 0.8); // 右上角相对偏移(宽度10%,高度80%)
renderer->AddActor2D(scalarBar);
}
//------------------------------------------------------------------------------
}
//属性切换
void Form_VTK::onPropertyChanged(int index)
{
if(!bIsInitCompleted) return;
if (index < 0 || !polyData || !propertyComboBox) return;
vtkPointData* pointData = polyData->GetPointData();
if (!pointData) return;
// 获取当前属性数组
QString strName = pointData->GetArrayName(index);
vtkDataArray* selectedArray = pointData->GetArray(strName.toStdString().c_str());
if (!selectedArray)
return;
// 关键步骤:设置活动标量
pointData->SetActiveScalars(selectedArray->GetName());
// 更新颜色映射范围
double range[2];
selectedArray->GetRange(range); // 获取属性值范围[min, max]
qDebug() << strName << " 范围: " << range[0] << "到" << range[1];
if (!std::isfinite(range[0]) || !std::isfinite(range[1])) {
qDebug() << "属性范围包含无效数值(NaN或无穷大)";
return;
}
double minVal = range[0];
double maxVal = range[1];
double midVal = (minVal + maxVal) * 0.5;
qDebug() << "minVal:" << minVal << " midVal:" << midVal << " maxVal:" << maxVal;
// 创建发散色阶(蓝-灰-红)
colorFunc->RemoveAllPoints();
colorFunc->SetColorSpaceToDiverging();
colorFunc->AddRGBPoint(minVal, 0.23, 0.299, 0.754); // 深蓝 (最小值)
colorFunc->AddRGBPoint(midVal, 0.865, 0.865, 0.865); // 中性灰 (中间值)
colorFunc->AddRGBPoint(maxVal, 0.706, 0.016, 0.15); // 深红 (最大值)
colorFunc->Build();
// 配置Mapper
mapper->SetInputData(polyData);
mapper->SetLookupTable(colorFunc);
mapper->SetScalarModeToUsePointData();
mapper->ColorByArrayComponent(strName.toStdString().c_str(), -1);
mapper->SetScalarRange(minVal, maxVal); // 设置完整数据范围
mapper->ScalarVisibilityOn();
mapper->Modified();
// 配置Actor
actor->SetMapper(mapper);
// 配置渲染器
renderer->AddActor(actor);
renderer->SetBackground(1.0, 1.0, 1.0);
//renderer->SetBackground(0.4, 0.4, 0.5); // 浅灰背景(类似ParaView)
renderer->ResetCamera();
// 更新颜色条(确保scalarBar有效)
configureScalarBar(false,strName);
// 触发渲染更新(确保renderWindow有效)
if (renderWindow)
{
renderWindow->AddRenderer(renderer);
vtkWidget->SetRenderWindow(renderWindow);
renderWindow->Render();
}
}
补充完整initVTKView()接口,我的要求是,先初始化init()并完成对VTK视图界面的初始化,然后loadVtkData()加载VTK对象a,然后unloadVtkData()卸载VTK对象a,最后loadVtkData()加载VTK对象b