使用VTK中的移动立方体(MC)算法对体素数据进行表面重构。

该文章介绍了一个处理txt格式数据文件的过程,首先读取包含3D空间点属性值的数据,然后利用vtkImageData填充数据并添加边界空气层。接着,应用移动立方体算法提取等值面,并进行渲染展示。代码示例展示了如何用VTK库实现这一系列操作。
摘要由CSDN通过智能技术生成

数据文件格式

数据文件(txt)举例:

3 6 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1

格式说明:

这样的一串数字,3 6 3分别表示z,y,x方向格点数,后面的3*6*3个数字就是从第0层开始每个点的属性值。

注意:

  1. z * y * x ;
  2. 这里的0、1、2代表不同的材料,0为空气,1为硅基底,2为多晶硅;
  3. 3 6 3 之后的数字是按照 x轴,y轴,z轴,逐个、逐行、逐层的顺序存储。

“天才”的数据格式。。。

整体架构流程

  1. 读取原始数据(数据特点:点与点之间的距离是恒定的)
  2. 对vtkImageData对象进行数据填充(vtkImageData可用于规则的离散点,符合需求)
  3. 使用移动立方体算法提取等值面
  4. 进行面绘制

读取原始数据

void readFile(std::vector<int> &data, int& size_z, int& size_y, int& size_x)
{
	std::ifstream infile("result_DRIE3_1cycle_etch2s_dep20.txt"); // 打开文件
	infile >> size_z >> size_y >> size_x;

	// 读取数据并存储到 vector 中
	int num;
	while (infile >> num) {
		data.push_back(num);
	}
}

数据填充

如果不加一圈空气提取会出现问题

	vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
	//需要在四周加一圈空气,所以所有维度都+2
	imageData->SetDimensions(maxPointsX+2, maxPointsY+2, maxPointsZ+2);//设置网格的尺寸
	imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
	imageData->SetSpacing(1.0, 1.0, 1.0);//设置间距
	unsigned char* voxelData = static_cast<unsigned char*>(imageData->GetScalarPointer());
	int k = 0;
	int count = 0;
	for (int i = -1; i <= maxPointsZ; ++i) {
		for (int j = -1; j <= maxPointsY; ++j) {
			for (int l = -1; l <= maxPointsX; ++l) {
				if (i == -1 || i == maxPointsZ || j == -1 || j == maxPointsY || l == -1 || l == maxPointsX)//加一圈空气
				{
					voxelData[k++] = 0;//设置空气的值为0
					continue;
				}
				if (datas[count++] == 0)
				{
					voxelData[k++] = 0;//设置空气的值为0
				}
				else
				{
					voxelData[k++] = 255;//设置其他值暂时都为255
				}
			}
		}
	}

使用MC算法提取等值面

注意这个是只有一个等值面的情况,如果有多个等值面,需要循环多次提取。

	vtkSmartPointer<vtkMarchingCubes> boneExtractor = vtkSmartPointer<vtkMarchingCubes>::New();
	boneExtractor->SetInputData(imageData);
	boneExtractor->SetValue(0, 255); // 设置提取的等值信息
	boneExtractor->Update();

渲染

vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(boneExtractor->GetOutputPort());
	mapper->ScalarVisibilityOff();

	vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
	actor->GetProperty()->SetColor(1.0,0,0);
	
	// 创建渲染器、渲染窗口和交互器
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->SetBackground(0.0, 0.0, 0.0); // 设置背景颜色

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);

	vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	//启用缩放、旋转和平移交互功能
	vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	interactor->SetInteractorStyle(style);

	// 渲染并启动交互
	renderWindow->Render();
	interactor->Start();

 

全部代码

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
using namespace std;
void readFile(std::vector<int> &data, int& size_z, int& size_y, int& size_x)
{
	std::ifstream infile("result_DRIE3_1cycle_etch2s_dep20.txt"); // 打开文件
	infile >> size_z >> size_y >> size_x;

	// 读取数据并存储到 vector 中
	int num;
	while (infile >> num) {
		data.push_back(num);
	}
}
int main()
{
	int maxPointsX, maxPointsY, maxPointsZ;
	std::vector<int> datas;
	readFile(datas, maxPointsZ, maxPointsY, maxPointsX);

	vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
	//需要在四周加一圈空气,所以所有维度都+2
	imageData->SetDimensions(maxPointsX+2, maxPointsY+2, maxPointsZ+2);//设置网格的尺寸
	imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
	imageData->SetSpacing(1.0, 1.0, 1.0);//设置间距
	unsigned char* voxelData = static_cast<unsigned char*>(imageData->GetScalarPointer());
	int k = 0;
	int count = 0;
	for (int i = -1; i <= maxPointsZ; ++i) {
		for (int j = -1; j <= maxPointsY; ++j) {
			for (int l = -1; l <= maxPointsX; ++l) {
				if (i == -1 || i == maxPointsZ || j == -1 || j == maxPointsY || l == -1 || l == maxPointsX)//加一圈空气
				{
					voxelData[k++] = 0;//设置空气的值为0
					continue;
				}
				if (datas[count++] == 0)
				{
					voxelData[k++] = 0;//设置空气的值为0
				}
				else
				{
					voxelData[k++] = 255;//设置其他值为255
				}
			}
		}
	}

	vtkSmartPointer<vtkMarchingCubes> boneExtractor = vtkSmartPointer<vtkMarchingCubes>::New();
	boneExtractor->SetInputData(imageData);
	boneExtractor->SetValue(0, 255); // 设置提取的等值信息
	boneExtractor->Update();

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(boneExtractor->GetOutputPort());
	mapper->ScalarVisibilityOff();

	vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
	actor->GetProperty()->SetColor(1.0,0,0);
	
	// 创建渲染器、渲染窗口和交互器
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->SetBackground(0.0, 0.0, 0.0); // 设置背景颜色

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);

	vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	//启用缩放、旋转和平移交互功能
	vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	interactor->SetInteractorStyle(style);

	// 渲染并启动交互
	renderWindow->Render();
	interactor->Start();

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值