VTK 的可视化方法:Glyph

VTK 的可视化方法:Glyph

模型的法向量数据是向量数据,因此法向量不能像前面讲到的通过颜色映射来显示。但是可以通过符号化(Glyphing)技术将法向量图形化显示。

Glyphing是一种基于图形的可视化技术,这些图像可以是简单的基本图形,如具有方向的椎体,也可以是更加复杂的图像。VTK中就是应用vtkGlyph3D类实现该功能的,并且可以支持Glyphing图形的缩放、着色、设置空间姿态等。使用该类时,需要接受两个输入:一个是需要显示的几何数据点集合;另一个是Glyph图形数据,为vtkPolyData数据。

标量、向量、张量

标量、向量、张量是可视化数据处理的 3 种数据类型。

  • 标量(scalar):只有一个数字的张量叫标量(也叫标量张量、零维张量、0D 张量)
  • 向量(vector):数字组成的数组叫作向量(vector)或一维张量(1D 张量)。一维张量只有一个轴。
  • 张量(Tensor):张量是一个多维数组,它是标量,向量,矩阵的高维扩展,是一个数据容器,张量是矩阵向任意维度的推广。

在这里插入图片描述

将多边形数据的采集点法向量标记成锥形符号

在读取和使用文件过程中,我们经常要用到法向量。这个例子展示了我们应该如何计算多边形数据的法向量并用vtkGlyph3D绘制圆锥型状将其标记出来。详细过程如下:

  1. 读取vtk文件构建多边形数据集;
  2. 使用vtkPolyDataNormals类计算多边形数据的 points 和 cell 的法向量,并将法向量由内侧翻转到外侧;
  3. 使用vtkMaskPoints类采样部分数据,为总数的十分之一, 保留输入数据中的点数据及其属性;
  4. 构建vtkGlyph3D对象,绘制形状设置为圆锥,将圆锥用一个过滤器做一个简单的偏移,数据源为采样点数据;
  5. 绘制法向量数据和符号数据。

完整代码:

#include "VTKGlyph.h"

#include <vtkConeSource.h>
#include <vtkPolyDataReader.h>
#include <vtkPolyDataNormals.h>
#include <vtkMaskPoints.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkGlyph3D.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

VTKGlyph::VTKGlyph(QWidget* parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	_pVTKWidget = new QVTKOpenGLNativeWidget();
	this->setCentralWidget(_pVTKWidget);
	// this->showMaximized();

	// 1. generate data
	// 创建法向量的符号:圆锥形
	vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
	cone->SetResolution(6);
	// or, read data
	vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("fran_cut.vtk");
	// 计算 poly data 中 points 和 cell 的法向量
	vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
	// 将多边形数据集作为法向量对象的数据输入
	normals->SetInputConnection(reader->GetOutputPort());
	// 将法线翻转,默认的法线方向指向内侧
	normals->FlipNormalsOn();
	// 由于读入的模型数据比较大,点比较多,因此使用 vtkMaskPoints 类采样部分数据,该类保留输入数据中的点数据及其属性,并支持点数据的采样
	vtkSmartPointer<vtkMaskPoints> maskPt = vtkSmartPointer<vtkMaskPoints>::New();
	maskPt->SetInputConnection(normals->GetOutputPort());
	// 设置采样率为 1/10
	maskPt->SetOnRatio(10);
	// 打开随机采样模式
	maskPt->RandomModeOn();
	// 偏移
	vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
	transform->Translate(0.5, 0, 0);

	// 2. filter
	vtkSmartPointer<vtkTransformPolyDataFilter> filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	// 将法向量的符号:圆锥形设置偏移
	filter->SetInputConnection(cone->GetOutputPort());
	filter->SetTransform(transform);

	vtkSmartPointer<vtkGlyph3D> glyph = vtkSmartPointer<vtkGlyph3D>::New();
	// 设置被标识的点
	glyph->SetInputConnection(maskPt->GetOutputPort());
	// 设置被偏移的符号
	glyph->SetSourceConnection(filter->GetOutputPort());
	// 设置向量为法线方向
	glyph->SetVectorModeToUseNormal();
	glyph->SetScaleModeToScaleByVector();
	// 设置比例,缩小法向量的大小
	glyph->SetScaleFactor(0.004);

	// 3. mapper
	vtkSmartPointer<vtkPolyDataMapper> franMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	vtkSmartPointer<vtkPolyDataMapper> spikeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();

	// 4. actor
	vtkSmartPointer<vtkActor> franActor = vtkSmartPointer<vtkActor>::New();
	vtkSmartPointer<vtkActor> spikeActor = vtkSmartPointer<vtkActor>::New();

	// 5. renderer
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->SetBackground(0.3, 0.6, 0.3);

	// 6. connect
	franMapper->SetInputConnection(normals->GetOutputPort());
	spikeMapper->SetInputConnection(glyph->GetOutputPort());
	franActor->SetMapper(franMapper);
	spikeActor->SetMapper(spikeMapper);
	renderer->AddActor(franActor);
	renderer->AddActor(spikeActor);

	this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
	this->_pVTKWidget->renderWindow()->Render();
}

VTKGlyph::~VTKGlyph()
{}

运行结果:

在这里插入图片描述

拉近摄像头,按W键切换成线框模式:

在这里插入图片描述

可以看出一个个小锥体都长在点上,代表网格的法向量。

参考

  1. https://www.bilibili.com/video/BV1sY41197GT
  2. https://blog.csdn.net/weixin_52194015/article/details/135698359
  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用VTK可视化三维数组,需要将数组转换为VTK数据对象。以下是一些简单的步骤: 1. 导入必要的VTK库和头文件。 ``` #include <vtkSmartPointer.h> #include <vtkStructuredPoints.h> #include <vtkStructuredPointsReader.h> #include <vtkStructuredPointsWriter.h> ``` 2. 创建一个vtkStructuredPoints对象并设置其属性。 ``` vtkSmartPointer<vtkStructuredPoints> structuredPoints = vtkSmartPointer<vtkStructuredPoints>::New(); structuredPoints->SetDimensions(xDim, yDim, zDim); // 设置数组的维度 structuredPoints->SetOrigin(0, 0, 0); // 设置原点 structuredPoints->SetSpacing(1, 1, 1); // 设置间距 ``` 3. 将数组数据添加到vtkStructuredPoints对象中。 ``` vtkSmartPointer<vtkDoubleArray> dataArray = vtkSmartPointer<vtkDoubleArray>::New(); dataArray->SetName("Data"); // 设置数组的名称 dataArray->SetNumberOfComponents(1); dataArray->SetNumberOfTuples(xDim * yDim * zDim); for(int i = 0; i < xDim; i++) { for(int j = 0; j < yDim; j++) { for(int k = 0; k < zDim; k++) { double value = array[i][j][k]; // 从数组中获取数据 dataArray->SetValue(i * yDim * zDim + j * zDim + k, value); // 将数据添加到vtkDoubleArray对象中 } } } structuredPoints->GetPointData()->SetScalars(dataArray); // 将vtkDoubleArray对象添加到vtkStructuredPoints对象中 ``` 4. 创建一个vtkStructuredPointsWriter对象并将vtkStructuredPoints对象写入文件。 ``` vtkSmartPointer<vtkStructuredPointsWriter> writer = vtkSmartPointer<vtkStructuredPointsWriter>::New(); writer->SetFileName(filename.c_str()); // 设置文件名 writer->SetInputData(structuredPoints); // 设置写入数据对象 writer->Write(); // 写入文件 ``` 5. 最后,使用VTK可视化工具显示vtkStructuredPoints对象。 ``` vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); renderWindow->AddRenderer(renderer); vtkSmartPointer<vtkStructuredPointsReader> reader = vtkSmartPointer<vtkStructuredPointsReader>::New(); reader->SetFileName(filename.c_str()); // 读取文件 vtkSmartPointer<vtkStructuredPointsMapper> mapper = vtkSmartPointer<vtkStructuredPointsMapper>::New(); mapper->SetInputConnection(reader->GetOutputPort()); // 设置vtkStructuredPoints对象 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); renderer->AddActor(actor); vtkSmartPointer<vtkInteractorStyleTrackballCamera> interactorStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New(); vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); renderWindowInteractor->SetInteractorStyle(interactorStyle); renderWindowInteractor->SetRenderWindow(renderWindow); renderWindowInteractor->Initialize(); renderWindowInteractor->Start(); ``` 以上就是使用VTK可视化三维数组的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值