VTK可视化之符号化
- vtkGlyph3D是一个符号化的算法工具
- vtkGlyph3D类可以创建一个具有大小、方向和颜色的符号,并支持图形缩放、着色、设置空间姿态等
- 输入对象中的每个点都可以用符号来可视化
- vtkGlyph3D 对象符号被配置使用点属性法矢量作为方向向量
- 也可以使用SetVectorModeToUseVector()方法用矢量数据代替法矢量
- 根据矢量值的大小,按比例绘制符号的大小。
- vtkGlyph3D对象需要接受两个输入:几何数据点集合、
Glyph
图形数据(vtkPolyData数据)。几何数据点集合来自求完法向量的图像,Glyph
图形数据用于在点集合处显示法向量。
Demo1 给符号标记颜色
- 创建点集
- 创建3维的unsigned char矢量数组
- 将点集设置给多边形数据集对象,并将属性数组设置为点集的属性
- 创建符号对象,设置符号形状数据,及被标记的多边形数据,关键点是按比例,标量或矢量/法向量的幅度值来设置符号的颜色SetColorModeToColorByScalar
- 设置符号的比例则需打开glyph3D->ScalingOff();并调用SetScaleModeToScaleByScalar
#include <vtkSmartPointer.h>
#include <vtkPointData.h>
#include <vtkCubeSource.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkGlyph3D.h>
#include <vtkCellArray.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkUnsignedCharArray.h>
int main()
{
// 创建点集,用于被标记
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(0,0,0);
points->InsertNextPoint(5,0,0);
points->InsertNextPoint(10,0,0);
// 创建一个三维的字符型标量数组
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetName("colors");
colors->SetNumberOfComponents(3);//设置每个元素的维度
colors->SetNumberOfTuples(3);//设置元素的个数
unsigned char r[3] = {255,0,0};
unsigned char g[3] = {0,255,0};
unsigned char b[3] = {0,0,255};
colors->SetTuple3(0,r[0],r[1],r[2]);
colors->SetTuple3(1,g[0],g[1],g[2]);
colors->SetTuple3(2,b[0],b[1],b[2]);
/*
// 创建一个一维的浮点型标量数组 -- 作为颜色属性
vtkSmartPointer<vtkFloatArray> scales = vtkSmartPointer<vtkFloatArray>::New();
scales->SetName("scales");
scales->InsertNextValue(1.0);
scales->InsertNextValue(2.0);
scales->InsertNextValue(3.0);
glyph3D->SetScaleModeToScaleByScalar();
glyph3D->ScalingOn();
*/
// 将点集设置到一个多边形数据集中
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
// 设置点集的标量属性
polydata->GetPointData()->SetScalars(colors);
// 创建标记符号的形状,这里设置为cube
vtkSmartPointer<vtkCubeSource> cubeSource = vtkSmartPointer<vtkCubeSource>::New();
// 创建一个3D符号对象
vtkSmartPointer<vtkGlyph3D> glyph3D = vtkSmartPointer<vtkGlyph3D>::New();
// 按比例,标量或矢量/法向量的幅度值来设置符号的颜色
glyph3D->SetColorModeToColorByScalar();
//设置标记符号的源对象数据,这里是cube
glyph3D->SetSourceConnection(cubeSource->GetOutputPort());
// 设置需要被标记的多边形数据集
glyph3D->SetInputData(polydata);
// 关闭几何体源数据的缩放
glyph3D->ScalingOff();
// 触发流水线执行
glyph3D->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
// 将符号对象的数据设置到mapper中
mapper->SetInputConnection(glyph3D->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// 可视化
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(1,1,1); // Background color white
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
Demo2 将多边形数据的采集点法向量标记成锥形符号
- 读取stl文件构建多边形数据集
- 计算多边形数据的点法向量
- 使用vtkMaskPoints类采样部分数据,保留输入数据中的点数据及其属性
- 构建vtkGlyph3D对象,绘制形状设置为圆锥,数据源为采样点数据
- 绘制法向量数据和符号数据
#include "vtkSmartPointer.h"
#include "vtkPolyDataReader.h"
#include "vtkPolyDataNormals.h"
#include "vtkPolyDataMapper.h"
#include "vtkMaskPoints.h"
#include "vtkConeSource.h"
#include "vtkGlyph3D.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSTLReader.h"
#include "vtkProperty.h"
int main()
{
//读取模型文件
vtkSmartPointer<vtkSTLReader> obj = vtkSmartPointer<vtkSTLReader>::New();
obj->SetFileName("C:\\Users\\qiang.shen\\Desktop\\IronData\\XZW.stl");
// 计算模型每个面的法矢量,创建一个法向量对象
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
//计算单元法向量时,要保持单元法向量一致才能得到合理的法向量。SetConsistency()可以自动调整单元点的顺序;SetAutoOrientNormals()可以自动调整法向量方向。
//类vtkPolyDataNormals自动开启对锐边缘处理,如果检测到锐边缘,会将其分裂,使图形更加平滑,可通过SetSplitting()函数关闭该功能。
//三维平面的法向量是指垂直该平面的向量。某点的法向量为垂直该点切平面的法向量。
// 将多边形数据集作为法向量对象的数据输入
normals->SetInputConnection(obj->GetOutputPort());
// 指定锐边角度为30度
normals->SetFeatureAngle(30);
// 关闭单元法向量计算(单元法向量可以通过组成每个单元的任意两条边的叉乘向量归并化来表示)
normals->SetComputeCellNormals(0);
// 开启点法向量计算(点的法向量则是由使用该点的单元单元法向量的平均值表示)
normals->SetComputePointNormals(1);
// 开启正常方向的全局翻转
normals->SetFlipNormals(1);
// 如果检测到锐边缘,会将其分裂,使图形更加平滑
normals->SetSplitting(1);
vtkSmartPointer<vtkPolyDataMapper> objMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
objMapper->SetInputConnection(normals->GetOutputPort());
//由于读入的模型数据比较大,点比较多,因此使用vtkMaskPoints类采样部分数据,该类保留输入数据中的点数据及其属性,并支持点数据的采样
vtkSmartPointer<vtkMaskPoints> ptMask = vtkSmartPointer<vtkMaskPoints>::New();
ptMask->SetInputConnection(normals->GetOutputPort());
//创建符号——圆锥形
vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
cone->SetAngle(26.5651);
cone->SetHeight(1);
cone->SetRadius(0.5);
cone->SetResolution(6);
cone->SetCapping(1);
vtkSmartPointer<vtkGlyph3D> glyph = vtkSmartPointer<vtkGlyph3D>::New();
//设置被标识的点
glyph->SetInputConnection(normals->GetOutputPort());
//设置符号
glyph->SetSourceConnection(cone->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> glyphMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
glyphMapper->SetInputConnection(glyph->GetOutputPort());
vtkSmartPointer<vtkActor> glyphActor = vtkSmartPointer<vtkActor>::New();
glyphActor->SetMapper(glyphMapper);
glyphActor->GetProperty()->SetColor(1, 0, 0);
vtkSmartPointer<vtkActor> normalActor = vtkSmartPointer<vtkActor>::New();
normalActor->SetMapper(objMapper);
// Setup render window, renderer, and interactor
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(normalActor);
renderer->AddActor(glyphActor);
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
平面切割
- 需要构建一个切割面,指定切割面中心SetOrigin(),及切割面的法向量SetNormal().SetValue()和GenerateValue()可以设定切割面的个数及位置
- 设置切割过滤器对象vtkCutter, 指定被切割的数据集,及切割面隐函数vtkPlane
- 计算数据集在指定点的位置的属性vtkProbeFilter,指定切割对象的数据集,及被切割的数据集
- 绘制vtkProbeFilter对象计算后的数据集(绘制的是切个对象的轮廓)
#include "vtkPlane.h"
#include "vtkSTLReader.h"
#include "vtkPlane.h"
#include "vtkPolyData.h"
#include "vtkProbeFilter.h"
#include "vtkDataSetMapper.h"
#include "vtkPointData.h"
#include "vtkSmartPointer.h"
#include "vtkCutter.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
int main()
{
//读取模型文件,被切割的数据
vtkSmartPointer<vtkSTLReader> obj = vtkSmartPointer<vtkSTLReader>::New();
obj->SetFileName("C:\\Users\\qiang.shen\\Desktop\\IronData\\XZW.stl");
//创建切割平面
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
//设定剪切平面在被剪切的数据中心位置
vtkSmartPointer<vtkPolyData> polyData = obj->GetOutput();
plane->SetOrigin(polyData->GetCenter());
plane->SetNormal(-0.287, 0, 0.9579);
//过滤器类,利用隐函数对数据进行剪切
vtkSmartPointer<vtkCutter> planeCut = vtkSmartPointer<vtkCutter>::New();
// 设置被裁剪的数据集
planeCut->SetInputConnection(obj->GetOutputPort());
//设定隐函数
planeCut->SetCutFunction(plane);
//planeCut->SetValue(0, 50);
planeCut->GenerateValues(10, 0, 500);
//计算数据集在指定点的位置的属性
vtkSmartPointer<vtkProbeFilter> probe = vtkSmartPointer<vtkProbeFilter>::New();
//计算平面在数据集通过点的属性
probe->SetInputConnection(planeCut->GetOutputPort());
//被计算的数据集
probe->SetSourceConnection(obj->GetOutputPort());
vtkSmartPointer<vtkDataSetMapper> cutMapper = vtkSmartPointer<vtkDataSetMapper>::New();
cutMapper->SetInputConnection(probe->GetOutputPort());
//得到数据点集属性值的范围
vtkSmartPointer<vtkPointData> pData = vtkSmartPointer<vtkPointData>::New();
pData = polyData->GetPointData();
//设定属性值范围
//cutMapper->SetScalarRange(pData->GetScalars()->GetRange());
cutMapper->ScalarVisibilityOn();
vtkSmartPointer<vtkActor> cutActor = vtkSmartPointer<vtkActor>::New();
cutActor->SetMapper(cutMapper);
// 可视化
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(cutActor);
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}