符号化是使用符号表示数据的一种可视化技术,符号可以简单也可以非常复杂, 在 VTK中 vtkGlyph3D 类可以创建一个具有大小、方向和用颜色表示的符号,输入数据对象中的每一个点都可以用符号来可视化。
vtkGlyph3D
vtkGlyph3D是一个过滤器,他会将固定的几何数据(符号数据)复制到输入的数据集的每一个点上,符号是通过void SetSourceData (vtkPolyData *pd)函数设置的,vectorMod和scalarMod会决定符号的方向和缩放比例。甚至还可以定义一个符号表,使用scalar的幅度对应每一个符号。
符号的缩放由两个因素决定:
- scalarMod
- scale
首先是scalarMod,vtk提供了这么几种可用的Mod
void SetScaleModeToScaleByScalar () //使用每个点上的scalar数据控制缩放 void SetScaleModeToScaleByVector () //使用点上的vector数据控制缩放 void SetScaleModeToScaleByVectorComponents () void SetScaleModeToDataScalingOff () // 关闭使用数据控制缩放
需要使用符号大小体现数据的大小时,可以选择对应的数据进行控制,如果不需要则可以将此功能关闭。
然后符号本身的scale,有时候输入数据过大会导致符号的大小不是那么好控制,所以又在这个基础上乘上一个比例。
void SetScaleFactor (double) //设置缩放比例
void SetVectorModeToUseVector () //使用vector数据控制方向 void SetVectorModeToUseNormal () //使用法向数据控制方向 void SetVectorModeToVectorRotationOff () //关闭方向控制 void SetVectorModeToFollowCameraDirection () //使符号方向跟随相机的方向
根据以上,可知符号化的整个过程,首先需要输入数据集和符号数据源,然后要决定是否要使用数据映射符号的缩放以及设置映射之后的符号缩放比例,最后决定符号的方向是由矢量、法向来控制。
这里需要特别注意的是,在设置缩放和方向mod的时候,一定要确定输入数据集包含的数据类型,如果都是空数据最好将mod设置为关闭状态,否则可能导致符号不显示。
需要使用数据映射符号颜色,参照之前标量颜色映射的方法就可以了。
示例
修改之前等值面提取的示例,实现使用箭头显示小心心表面的法向。
vtkNew<vtkStructuredGrid> structuredGrid;
vtkNew<vtkPoints> points;
vtkNew<vtkFloatArray> scalars;
unsigned int gridSize = 40;
//构造一个点云,使用函数为点云构造标量值
for (unsigned int i = 0; i < gridSize; i++)
{
for (unsigned int j = 0; j < gridSize; j++)
{
for (unsigned int k = 0; k < gridSize; k++)
{
points->InsertNextPoint(i, j, k);
//实现函数 (x^2 + (9/4) y^2 + z^2 - 1)^3 - x^2*z^3 - (9/80) y^2*z^3 =F, {x, -2, 2}, {y, -2, 2}, {z, -2, 2}
double x = (i - (gridSize / 2.0)) / 10.0;
double y = (j - (gridSize / 2.0)) / 10.0;
double z = (k - (gridSize / 2.0)) / 10.0;
scalars->InsertNextTuple1(pow(x * x + (9.0 / 4.0) * y * y + z * z - 1.0, 3) - x * x * pow(z, 3) - (9.0 / 80.0) * y * y * pow(z, 3));
}
}
}
//设置网格大小
structuredGrid->SetDimensions(gridSize, gridSize, gridSize);
//附加数据
structuredGrid->SetPoints(points);
structuredGrid->GetPointData()->SetScalars(scalars);
//设置映射器
vtkNew<vtkDataSetMapper> gridMapper;
gridMapper->SetInputData(structuredGrid);
gridMapper->ScalarVisibilityOff();
vtkNew<vtkActor> gridActor;
gridActor->SetMapper(gridMapper);
gridActor->GetProperty()->SetOpacity(0.3);
//设置等值线过滤器
vtkNew<vtkContourFilter> contourFilter;
contourFilter->SetInputData(structuredGrid);
//为标量为0时取一个等值面
contourFilter->SetValue(0, 0);
contourFilter->Update();
//创建颜色表 这里只输入颜色值的数量,然后自动生成表
vtkNew<vtkLookupTable> lut;
lut->SetTableRange(scalars->GetRange());
lut->Build();
//为生成的等值面添加法向
vtkNew<vtkPolyDataNormals> normals;
normals->SetInputConnection(contourFilter->GetOutputPort());
normals->SetFeatureAngle(45);
normals->Update();
vtkNew<vtkDataSetMapper> contourMaper;
contourMaper->SetInputData(normals->GetOutput());
contourMaper->SetLookupTable(lut);
contourMaper->SetScalarRange(scalars->GetRange());
vtkNew<vtkActor> contourActor;
contourActor->SetMapper(contourMaper);
//符号化等值面的法向
vtkNew<vtkMaskPoints> maskPoints;
maskPoints->SetInputData(normals->GetOutput());
maskPoints->Update();
vtkNew<vtkGlyph3D> glyph3D;
glyph3D->SetInputData(maskPoints->GetOutput());
vtkNew<vtkArrowSource> arrow;
arrow->Update();
glyph3D->SetSourceData(arrow->GetOutput());
glyph3D->SetScaleFactor(1);
glyph3D->SetVectorModeToUseNormal(); //使用法向控制方向
glyph3D->SetScaleModeToDataScalingOff(); //由于等值面上所有的点都为0,所以关闭缩放控制
glyph3D->Update();
vtkNew<vtkPolyDataMapper> glMapper;
glMapper->SetInputData(glyph3D->GetOutput());
glMapper->Update();
vtkNew<vtkActor> glActor;
glActor->SetMapper(glMapper);
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
vtkNew<vtkScalarBarActor> barActor;
barActor->SetLookupTable(lut);
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(contourActor);
renderer->AddActor(barActor);
renderer->AddActor(gridActor);
renderer->AddActor(glActor);
renderWindow->Render();
renderWindowInteractor->Start();

文章评论