数据文件格式
数据文件(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层开始每个点的属性值。
注意:
- 是 z * y * x ;
- 这里的0、1、2代表不同的材料,0为空气,1为硅基底,2为多晶硅;
- 3 6 3 之后的数字是按照 x轴,y轴,z轴,逐个、逐行、逐层的顺序存储。
“天才”的数据格式。。。
整体架构流程
- 读取原始数据(数据特点:点与点之间的距离是恒定的)
- 对vtkImageData对象进行数据填充(vtkImageData可用于规则的离散点,符合需求)
- 使用移动立方体算法提取等值面
- 进行面绘制
读取原始数据
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;
}