#include <vtkAutoInit.h>
// 初始化所需的 VTK 渲染模块
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSmartPointer.h>
#include <vtkDICOMImageReader.h>
#include <vtkMarchingCubes.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDecimatePro.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkPolyDataNormals.h>
#include <vtkSTLWriter.h>
#include <vtkProperty.h>
int main(int argc, char* argv[])
{
// DICOM 图像的目录路径
const char* pathToDicomDirectory = "E:\\Dicom\\001"; // 替换为你实际的 DICOM 目录路径
// 用于从DICOM图像中分割骨骼组织的阈值
const double boneThreshold = 400; // 根据你的数据替换为合适的阈值
// 步骤 1: 读取 DICOM 图像
// 创建一个读取器来加载 DICOM 图像
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(pathToDicomDirectory); // 设置 DICOM 图像的目录
reader->Update(); // 更新读取器以加载图像
// 步骤 2: 用 Marching Cubes 提取骨骼
// 创建一个 Marching Cubes 滤波器来提取等值面
vtkSmartPointer<vtkMarchingCubes> mcubes = vtkSmartPointer<vtkMarchingCubes>::New();
mcubes->SetInputConnection(reader->GetOutputPort()); // 设置输入为读取的图像
mcubes->SetValue(0, boneThreshold); // 设置骨骼的等值面值
mcubes->Update();
// 步骤 3: 平滑网格
// 创建一个平滑滤波器来平滑网格
vtkSmartPointer<vtkSmoothPolyDataFilter> smoothFilter = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
smoothFilter->SetInputConnection(mcubes->GetOutputPort()); // 设置输入为 Marching Cubes 的输出
smoothFilter->SetNumberOfIterations(30); // 设置平滑迭代次数
smoothFilter->Update();
// 步骤 4: 计算法线以更好地可视化
// 计算法线以增强网格的光照效果
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
normals->SetInputConnection(smoothFilter->GetOutputPort()); // 输入为平滑后的数据
normals->SetFeatureAngle(60.0); // 设置法线计算的特征角
normals->Update();
// 步骤 5: 将结果保存为 STL 文件
// 创建一个 STL 写入器来保存输出网格
vtkSmartPointer<vtkSTLWriter> stlWriter = vtkSmartPointer<vtkSTLWriter>::New();
stlWriter->SetFileName("D:/output_bone_model.stl"); // 设置输出 STL 文件路径
stlWriter->SetInputConnection(normals->GetOutputPort()); // 设置写入网格的数据
int nstatus = stlWriter->Write(); // 将网格写入文件
// 步骤 6: 可视化结果
// 创建一个映射器将多边形数据映射用于可视化
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(normals->GetOutputPort()); // 映射处理后的数据用于可视化
// 创建一个演员来在场景中表示对象
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper); // 将映射器设置到演员
actor->GetProperty()->SetColor(0.5, 0.5, 0.5); // 设置演员颜色为骨骼白
// 创建一个渲染器来渲染场景
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor); // 将演员添加到渲染器
renderer->SetBackground(1, 1, 1); // 设置背景颜色为白色
// 创建一个渲染窗口来显示渲染器
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer); // 将渲染器添加到渲染窗口
// 创建一个渲染窗口交互器用于用户交互
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow); // 将渲染窗口设置给交互器
// 渲染场景
renderWindow->Render(); // 初始渲染
// 开始交互过程
renderWindowInteractor->Start(); // 开始交互循环
return EXIT_SUCCESS;
}