vtk基本概念
渲染场景中数据的可视化表达通过vtkProp的子类负责,vtkPro子类 负责确定渲染场景中对象的位置、大小和方向等信息,它依赖于两个对象,一个是Mapper对象,负责存放数据和渲染信息,另一个是属性对象(vtkProperty),负责控制颜色、不同明度等
Mapper作用是将输入的数据转换为几何图元数据
Model坐标:定义模型时的坐标
World坐标:放置Actor的三维坐标,就是场景坐标。Actor的一个功能就是将Model坐标转换成World坐标,World坐标同时也是相机、灯光所在的坐标系统
View坐标是相机所看到的的坐标系统,XYZ取值是[-1,1],相机负责将World坐标转换成View坐标
Display坐标,就是显示坐标,坐标轴的取值为像素
渲染引擎负责数据的可视化表达,可视化管线是指用于获取或者创建数据、处理数据以及把数据写入文件或者传递给渲染引擎。
Source用于创建数据或者读取数据,传入到Filter生成新的数据,再到Mapper后传入引擎。Mapper是可视化管线的终点,也是可视化管线与渲染引擎的桥梁
可视化管线的连接,通过SetInputConnnection()和GetOutputPort(),连接时要求两部分的数据类型必须一直。如:vtkMarchingCubes要求输入的是vtkImageData类型,如果是vtkPolyData,则运行时出现错误。
管线执行时,当对数据对象做了更改时,不立即进行计算,只有当发出请求时,才开始计算。程序在调用 Render()函数时,Actor会收到渲染请求,接着请求Mapper给他发送数据,而Mapper会请求上一层的Filter数据,最后Filter请求Source。如果在重新读入数据以后,中间需要某些信息,在得到信息之前,必须调用update()函数。
vtkSmartPointer<vtkImageData> MyFunction()
{
vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
return myObjec;
}
vtkSmartPointer<vtkImageData> myImageData = MyFunction();//可以调用
//但是这样不行
vtkImageData* MyFunction()
{
vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
return myObjec;//返回时转成原始指针,引用计数为0,myObject被删除
}
vtkImageData* myImageData = MyFunction();//错误
对于这种情况
vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
myObject = reader->GetOutput();
//这里没有必要使用智能指针,因为没有创建新对象。用的是仍然是reader->GetOutput()对象
//直接使用
vtkImageData* myObject = reader->GetOutput();
运行时识别
vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
const char* type = reader->GetClassNaem();//"vtkBMPReader"
if(reader->isA("vtkBMPReader")){}; //true
//基类向子类转换类似于dynamic_cast
vtkBMPReader::SafeDownCast(readerBase);//只有vtkBMPReader是readerBase的派生类才行,否则返回空指针
//vtk还提供了调试状态输出函数print等
bmpReader->Print(std::cout);
vtk数据结构
数据对象表现的数据是可以被可视化管线处理的数据,只有当数据对象被组织成一种结构后,才能被VTK处理
vtkDataSet组织结构由拓扑和几何结构两部分组成。vtkDataSet由组织结构和属性数据组成。拓扑:对象构成形式,几何结构:对象空间位置关系。
Point构成了vtkDataSet的几何结构,Cell构成了拓扑结构。如三角形,必须定义三个坐标点 p1,p2,p3,如何连接(p1-p2-p3还是p3-p2-p1)构成了拓扑。总结,点数据(坐标数据)就是几何结构。其他的都是拓扑结构,如vtkLine、vtkVertex
一系列有序的点有序的连接就是单元。
顶点列表由点的索引号表示按照顺序表示。单元由单元类型(六面体)和顶点列表组成,如果不指定单元类型,则不确定形状。
数据集类型由组织 结构决定,并决定了点和单元之间的相互关系。如网格。
属性数据,可与点数据或者单元数据相关联,也可以与单元的某些成分相关联,如单元数据 的某个边
vtkPointData和 vtkCellData表示数据集的属性
数据通过vtkDataArray的形式存储。元祖的组分个数就是元祖的大小,即每个元组里面有几个值。
vtk的数据对象是作为vtkDataArray的数组实现。也就是数据数组的数组。
vtk数据读写
场景的导入与导出是指将宣传场景中的对象,包括相机、光照 、Actor属性、变化矩阵等写入或者导出文件。
vtk图像处理
vtk图形处理
默认情况下,mapper优先使用点标量数据进行颜色映射,当没有可用的点标量数据时,会使用可用的单元标量数据。
vtk提供的常用数据源:vtkArrowSource、vtkCubeSource、vtkCylinderSource、vtkDiskSource、vtkLineSource、vtkPlaneSource、vtkSphereSource、vtkConeSource
vtkMaskPoints设置采样部分数据
vtkMassProperties | 计算体积、表面积、最大最小单元面积 |
---|---|
vtkDijkstraGraphGeodesicPath | 测地距离,两个点沿着模型表面的最短距离 |
vtkOutlineFilter | 包围盒 |
vtkPolyDataNormals | 计算点和单元法向量 |
vtkCurvatures | 计算曲率 |
vtkSmoothPolyDataFilter | 网格平滑 |
vtkFeatureEdges | 封闭性检测 |
vtkFillHolesFilter | 将不封闭的洞填充 |
vtkPolyDataConnectivityFilter | 连通区域分析 |
vtkDelaunay2D | 二维三角剖分 |
vtkAppendPolyData可以实现vtkPolyData的合并
纹理映射,需要将纹理空间的映射分解为两部,需要映入一个包围景物的中介三维曲面作为中介媒介。先将纹理映射到中介面,然后再将中界面映射到物体。
体绘制
VTK交互与Widget
//1定义回调函数
void MyCallbackFunc(vtkObject* obj,unsigned long eid,void* clientdata,void* calldata)
{
//obj,调用时间的对象,即调用AddObserver()函数的对象
//eid,事件id
//clentdata,与vtkCallbackCommand实例相关联的数据,回调函数里需要访问主程序里的数据时,由主程序向回调函数传递的数据。可用vtkCallbackCommand::SetClientData()设置
//calldata,执行vtkObject::InvokeEvent()函数,随着回调函数发送的数据
}
//2创建vtkCallBackCommand对象
vtkSmartPointer<vtkCallbackCommand> mouseCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
mouseCallback->SetCallback(MyCallbackFunc);
//3将vtkCallbackCommand对象添加到观察者列表。
interactor->AddObserver(vtkCommand::LeftButtonPressEvent, mouseCallback);
//也可以直接从vtkCommand类中派生子类来实现
//1、重写类
class vtkMyCallback : public vtkCommand
{
public:
static vtkMyCallback *New()
{ return new vtkMyCallback; }
void SetObject(vtkConeSource* cone)//用于主程序向vtkMyCallback传数据
{
m_Cone = cone;
}
virtual void Execute(vtkObject *caller, unsigned long eventId, void* callData)
{//程序所要实现的功能
std::cout<<"Left button pressed.\n"
<<"The Height: "<<m_Cone->GetHeight()<<"\n"
<<"The Radius: "<<m_Cone->GetRadius()<<std::endl;
}
private:
vtkConeSource *m_Cone;
};
//第二步
vtkSmartPointer<vtkMyCallback> callback = vtkSmartPointer<vtkMyCallback>::New();
callback->SetObject(cone);//cone之前已经定义
//第三步
iren->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
vtk自定义GUI程序
vtkEventQtSlotConnect类可以实现VTK事件与Qt槽函数的连接
vtkEventQtSlotConnect* m_Connections = vtkEventQtSlotConnect::New();
m_Connections->Connect(m_QVTKWidget->GetRenderWindow()->GetInteractor(),vtkCommand::MouseMouseEvent,this,SLOT(updata(vtkObject*)));
//槽函数
void updateCoords(vtkObject* obj)
{
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
}
自定义vtk类
//1选择基类
//定义类的构造函数,析构函数,赋值运算符和拷贝构造函数
//内部都是通过New()静态函数生成,构造、析构、都定义为protected类型,赋值=和拷贝构造都要定义为private,切不做实现
//2定义标准创建和算出函数 New()和Delete()
//New()必须覆盖父类的方法,Delete()直接继承vtkObjectBase类即可
//实现文件构造函数之前,加入vtkStandardNewMacro(myClassName)
//3定义vtk基本函数。GetClassNameInternal()、IsTypeOf()、IsA()、SafeDownCast()、NewInstanceInternal()、NewInstance()实现这些,不用重写,只是需要vtk宏定义vtkTypeMacro(myClassName,vtkObject)
//4添加成员变量和相关函数,对于Set()和Get()函数,可以使用vtkSetMacro和vtkGetMacro
//5增加PrintSelf函数 打印对象状态 调试标志、引用计数等