VTK教程4--------打开vtk文件源码分析

如果你已经理解了上一讲的源码,那么可以直接拖到本文结尾分享的链接中下载文件打开。
vtk中的三维重建必须包含第二讲中的所有要素,也就是数据–>映射器–>演员–>渲染器–>渲染窗口,这个流水线管道,在构造函数中:

CvtkdlgDlg::CvtkdlgDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_VTKDLG_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	this->pvtkActor = vtkActor::New();
	this->pvtkDataSetMapper = vtkDataSetMapper::New();
	this->pvtkDataSetReader = nullptr;
	this->pvtkRenderer = vtkRenderer::New();

	this->pvtkMFCWindow = nullptr;

	this->ptBorder = CPoint(0, 0);
}

上述代码初始化了映射器,演员,渲染器。pvtkMFCWindow是渲染窗口,在这里初始化为nullptr,原因是pvtkMFCWindow的初始化必须晚于Picture Control控件初始化,也就是说pvtkMFCWindow初始化的时候Picture Control必须已经ready,然而在C++编程中,很难确认两个类的初始化顺序(插句题外话,以前调试代码的时候发现,如果在main函数之前需要使用STL的map,这时候在不同平台下会有不同的表现,比如在visual studio上运行尚好,换到gcc上面就崩溃了,定位出来是红黑树出问题了)。数据的准备和第二讲中的数据有所区别,在这里通过的是pvtkDataSetReader获取,当然,在初始化的时候根本没有得到文件路径,所以也初始化为nullptr。

接下来看 CvtkdlgDlg::OnInitDialog中的代码:

    this->pvtkMFCWindow = new vtkMFCWindow(this->GetDlgItem(IDC_STATIC));
	CRect cRectClient;
	this->pvtkMFCWindow->GetClientRect(&cRectClient);
	this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer);
	execute_pipeline();

这里干的第一件事,初始化pvtkMFCWindow,在OnInitDialog这个过程中,Picture Control控件已经ready,接下来的代码就是获取Picture Control控件的坐标,然后让pvtkMFCWindow浮在Picture控件上,事实上,vtk渲染窗口并不是真正的嵌入到了MFC中,它只是和MFC的Picture控件保持同样的位置(控件最小化,vtk渲染窗口最小化,控件移动位置,vtk渲染窗口跟着移动),这个结论来自于一篇论文,暂时找不着了,就不引用了。

接下来分析execute_pipeline函数:

void CvtkdlgDlg::execute_pipeline()
{
	if (this->pvtkDataSetReader)
	{
		this->pvtkDataSetMapper->SetInputConnection(this->pvtkDataSetReader->GetOutputPort());
		this->pvtkActor->SetMapper(this->pvtkDataSetMapper);
		this->pvtkActor->GetProperty()->SetColor(0.0, 0.0, 1.0);
		this->pvtkRenderer->SetBackground(1.0, 1.0, 1.0);
		this->pvtkRenderer->AddActor(this->pvtkActor);
	}
	else
	{
		this->pvtkRenderer->SetBackground(1.0, 1.0, 1.0);
	}
	this->pvtkRenderer->ResetCamera();
}

这个函数干啥了?也就是类似于第二讲中把流水线管道组装起来了,画一个示意图:
VTK教程4--------打开vtk文件源码分析_第1张图片
不过在本例中多了点设置,就是设置了一下演员颜色和渲染器背景色,这里大家可以尝试修改了看看效果。
最后看下打开文件的代码:

void CvtkdlgDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	//CDialogEx::OnOK();
	CString sz = _T("MyType Files (*.vtk)|*.vtk");
	CFileDialog dlg(true, _T(".*"), NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, sz, this);
	if (IDOK == dlg.DoModal())
	{
		this->input_path = dlg.GetPathName();
		UpdateData(false);
		this->pvtkRenderer->RemoveActor(this->pvtkActor);
		std::string str(CT2A(dlg.GetPathName()));
		

		if (!this->pvtkDataSetReader)
			this->pvtkDataSetReader = vtkDataSetReader::New();
		this->pvtkDataSetReader->SetFileName(str.c_str());
		execute_pipeline();
		if (this->pvtkMFCWindow)
			this->pvtkMFCWindow->RedrawWindow();
	}
}

这个代码的作用很简单,创建一个窗口,从窗口中获取打开文件的路径(使用了过滤器,过滤扩展名为vtk的文件)。另外,做了一些简单的校验,比如已经有打开的文件了,需要先删除再重新打开。
好了,我们再了解一些其他的东西,如果你用文本工具打开vtk文件,会发现里面就是一些点的坐标,非常多的点,在文件的后半部分会描述哪三个点构成了一个面,那么我们是不是可以在打开文件的时候只显示点,或者显示三角网格。在execute_pipeline函数中添加如下代码,注意看注释,只添加了一行代码:

	this->pvtkActor->SetMapper(this->pvtkDataSetMapper);
	this->pvtkActor->GetProperty()->SetColor(0.0, 0.0, 1.0);
	this->pvtkActor->GetProperty()->SetRepresentationToPoints(); //新添加代码,就一行
	this->pvtkRenderer->SetBackground(1.0, 1.0, 1.0);

放一个对比图:
VTK教程4--------打开vtk文件源码分析_第2张图片
这个图形还是太复杂了一些,如果是一个简单的图形,看起来要明显一些,比如下面的图像,一个大脑海马体的图像:
VTK教程4--------打开vtk文件源码分析_第3张图片
还可以将这行代码替换成现实三角网格,只修改了一行代码:

	this->pvtkActor->GetProperty()->SetColor(0.0, 0.0, 1.0);
	this->pvtkActor->GetProperty()->SetRepresentationToWireframe(); //修改的代码,只一行
	this->pvtkRenderer->SetBackground(1.0, 1.0, 1.0);

整体的对比图如下:
VTK教程4--------打开vtk文件源码分析_第4张图片
好了打开vtk文件的教程就到这里。
持续更新中。。。

数据下载看这里–>vtk脚踝数据
更多VTK教程,请VX搜索CodeKit。

你可能感兴趣的:(VTK教程)