使用颜色映射标量数据是数据可视化中为了表现多个维度的数据时常用的一种手段
要作出这种图,数据类型一般为一个空间中的平面数据或者三维模型数据再加上一个或者多个的标量数据,在VTK中使用这样的数据类型需要了解两个关键类,vtkDataSetAttributes和vtkDataSet。
vtkDataSet
vtkDataSet是一个抽象类,不能直接实例化,它是VTK所有数据集类型的父类,主要为数据集类型声明了一些通用接口以及成员。
从这个继承树中可以看到vtkDataSet所有的子类。
实现颜色标量映射主要关注的只有两个接口:
这个两个数据分别对应的是单元数据集点数据集。
单元数据集中的单元指得是计算机图形的图元集合,如果是多边形数据集那么它就是一个三角网格中所有三角形的集合,如果使用结构或者非结构化网格数据,那么它就是网格单元数据的集合。
点数据集合是单元集合中所用到所有的点的集合,根据数据集的类型不同,包含的数据也略微有点不同。
vtkDataSetAttributes
上述的vtkCellData和vtkPointData都继承于vtkDataSetAttributes,它可以用于包含标量、向量、法线、纹理坐标、张量、全局 id、谱系 id 和字段数据等数据。
// Description: // Set/Get the scalar data. int SetScalars(vtkDataArray* da); int SetActiveScalars(const char* name); vtkDataArray* GetScalars();// Description: // Set/Get the vector data. int SetVectors(vtkDataArray* da); int SetActiveVectors(const char* name); vtkDataArray* GetVectors();// Description: // Set/get the normal data. int SetNormals(vtkDataArray* da); int SetActiveNormals(const char* name); vtkDataArray* GetNormals();// Description: // Set/Get the texture coordinate data. int SetTCoords(vtkDataArray* da); int SetActiveTCoords(const char* name); vtkDataArray* GetTCoords();// Description: // Set/Get the tensor data. int SetTensors(vtkDataArray* da); int SetActiveTensors(const char* name); vtkDataArray* GetTensors();// Description: // Set/Get the global id data. int SetGlobalIds(vtkDataArray* da); int SetActiveGlobalIds(const char* name); vtkDataArray* GetGlobalIds();// Description: // Set/Get the pedigree id data. int SetPedigreeIds(vtkAbstractArray* da); int SetActivePedigreeIds(const char* name); vtkAbstractArray* GetPedigreeIds();
以上接口对应了每种数据的获取与设置,每种数据似乎可以添加多个序列,然后可以使用序列名称调整当前使用的数据,序列名称通过vtkDataArray类setName函数进行设置。序列数据中的顺序需要对应实际数据的顺序。这里的顺序指的是ID,如Point数据,每个点都会有一个ID,那么为这些点数据附加标量数据的时候,标量数据的传入顺序就需要与id一一对应,如果是cellData那么也同理。
vtkLookupTable
这个类提供一个从标量到颜色的映射表
//设置颜色的过度模式 void SetRamp(int); void SetRampToLinear();//线性 void SetRampToSCurve();//s曲线 void SetRampToSQRT();//y=sqrt(x) int GetRamp(); //设置颜色的与标量的映射模式 void SetScale(int); void SetScaleToLinear();//线性 void SetScaleToLog10();//对数 int GetScale(); void SetTableRang(double r[2]);//设置标量的范围(最小,最大值) void SetHueRang(double,double);//设置色调范围,取[0,1]之间 void SetSaturationRange(double,double);//设置饱和度,取[0,1]之间 void SetValueRange(double,double);//设置颜色值的取值范围,取[0,1]之间 void SetAlphaRange();//设置透明的取值范围,取[0,1]之间 void SetNanColor(double,double,double,double);//设置遇到Nan(非数)时使用的颜色 void SetBelowRangeColor(double,double,double,double);//设置当低于范围使用的颜色 void SetAboveRangeColor(double,double,double,double);//设置当超出范围时使用的颜色 void SetNumberOfTableValues(vtkIdType number);//设置颜色数量(色块) void SetTableValue(vtkIdType indx,double r, double g, double b, double a=1.0);//直接设置颜色值 //根据各种参数生成颜色表 void Build();
这是它的一些关键接口,通过这些结构可以构造一个完整的颜色表,然后再调用映射器对象的SetLookupTable (vtkScalarsToColors *lut)函数设置即可。
vtkScalarBarActor
这个类不是颜色映射时必须要的类,但是它可以直观的将颜色映射表显示到窗口上,非常的方便。
使用起来也很简单,它继承于vtkActor,只需要调用SetLookupTable (vtkScalarsToColors *)函数设置好对应的颜色表,然后将Actor添加到渲染器中即可
示例
//为三角形准备三个顶点 vtkNew<vtkPoints> points; points->InsertNextPoint(1, 0, 0); points->InsertNextPoint(0, 0, 0); points->InsertNextPoint(0, 1, 0); //生成点的标量数据 vtkNew<vtkIntArray> scalar; scalar->InsertNextTuple1(30); scalar->InsertNextTuple1(50); scalar->InsertNextTuple1(100); //使用顶点构建一个三角形 点使用ID传入 vtkNew<vtkTriangle> triangle; triangle->GetPointIds()->SetId(0, 0); triangle->GetPointIds()->SetId(1, 1); triangle->GetPointIds()->SetId(2, 2); //将三角形传入单元集 vtkNew<vtkCellArray> cellArray; cellArray->InsertNextCell(triangle); //为多边形数据添加单元集和点集 vtkNew<vtkPolyData> polydata ; polydata->SetPolys(cellArray); polydata->SetPoints(points); //为点数据添加标量 polydata->GetPointData()->SetScalars(scalar); vtkNew<vtkPolyDataMapper> mapper; mapper->SetInputData(polydata); mapper->SetScalarRange(scalar->GetRange()); mapper->Update(); //为映射器添加一个颜色映射表 vtkNew<vtkLookupTable> lookupTable; lookupTable->SetTableRange(scalar->GetRange()); lookupTable->Build(); mapper->SetLookupTable(lookupTable); //为窗口添加一个图例 vtkNew<vtkScalarBarActor> scalarBarActor; scalarBarActor->SetLookupTable(lookupTable); vtkNew<vtkActor> actor; actor->SetMapper(mapper); actor->GetProperty()->SetColor(255, 0, 0); vtkNew<vtkRenderer> renderer; vtkNew<vtkRenderWindow> window; window->AddRenderer(renderer); vtkNew<vtkRenderWindowInteractor> interactor; interactor->SetRenderWindow(window); renderer->AddActor(actor); renderer->AddActor(scalarBarActor); window->Render(); interactor->Start();
代码实现了一个三角形的构建,并为三角形的三个顶点添加标量,然后在显示时使用标量进行颜色映射,可以说这是一个最简单的标量映射的一个例子。
需要注意的是因为代码中是为point添加的标量,除了顶点以外的其他位置的标量值都是经过线性插值得到的。
再构建mapper对象和lookupTable对象是一定要为对象设置标量范围,否则会导致图例的范围与标量范围不一致,然后绘制出错误的图标。(我在这里翻了不少车)
最后的碎碎念
颜色映射的本质就是将标量数据附加到单元或者点上,然后再绘制的时候通过点集或者单元集的数据在颜色表中查找标量值对应的颜色,然后进行绘制。因为点是离散的,所以在标量绘制时可以选择为数据进行插值,这样就可以得到类似文章开头所展示的效果。
另外欢迎看到博客的有缘人留言一起讨论。
文章评论