VTK 数据处理:属性操作

VTK 数据处理:属性操作

回顾

VTK 中数据类型的继承关系:

在这里插入图片描述

数据结构:

  1. 几何结构:由 points 定义
  2. 拓扑结构:由 cells 定义

数据属性:主要有标量、矢量、法向量、张量、纹理坐标等。

在这里插入图片描述

VTK 的四种数据处理方法

  1. 几何操作
  2. 拓扑操作:比如等值面,流线、流管、流面、流带,Cutting&Probing等。
  3. 属性操作
  4. 混合操作:上面三种操作的综合使用。

实例 1:高程属性过滤器、颜色条、坐标系

构建一个球体,使用高程属性过滤器按高度对球体做颜色映射。使用 vtkScalarBarActor 类制作一个颜色条并显示,使用 vtkCameraOrientationWidget 类制作一个坐标轴并显示。

#include "VTKGenerateAttribute.h"

#include <vtkSphereSource.h>
#include <vtkNamedColors.h>
#include <vtkElevationFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkScalarBarActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

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

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

	vtkNew<vtkRenderer> renderer;
	this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
	this->_pVTKWidget->renderWindow()->Render();

	vtkNew<vtkNamedColors> colors;
	renderer->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());

	vtkNew<vtkSphereSource> sphere;
	sphere->SetThetaResolution(51);
	sphere->SetPhiResolution(17);
	sphere->SetRadius(0.5);

	// vtkElevationFilter:高程属性过滤器
	// 由用户设置一条线,将数据集里的所有点投影到这条线上,根据投影结果确定每个点的属性数据
	// 简单地说,就是进行颜色映射,让 RGB 的值从 LowPoint 到 HighPoint 进行变化
	vtkNew<vtkElevationFilter> elevation;
	elevation->SetInputConnection(sphere->GetOutputPort());
	elevation->SetLowPoint(0, 0, -0.5);
	elevation->SetHighPoint(0, 0, 0.5);
	double range[] = { -1, 1 };
	elevation->SetScalarRange(range);
	elevation->Update();
	elevation->GetOutput()->Print(std::cout);

	vtkNew<vtkPolyDataMapper> mapper;
	mapper->SetInputConnection(elevation->GetOutputPort());
	mapper->SetScalarRange(range);

	vtkNew<vtkActor> actor;
	actor->SetMapper(mapper);
	// 颜色条
	vtkNew<vtkScalarBarActor> colorBarActor;
	colorBarActor->SetLookupTable(mapper->GetLookupTable());
	colorBarActor->SetMaximumHeightInPixels(500);

	renderer->AddActor(actor);
	renderer->AddActor2D(colorBarActor);

	// 打开坐标系
	cameraOrientationWidget->SetParentRenderer(renderer);
	cameraOrientationWidget->On();
}

VTKGenerateAttribute::~VTKGenerateAttribute()
{}

运行结果:

在这里插入图片描述

elevation->GetOutput()->Print(std::cout) 打印的多边形信息如下所示:

vtkPolyData (00000165F9340AE0)
  Debug: Off
  Modified Time: 1468
  Reference Count: 1
  Registered Events: (none)
  Information: 00000165FB8C9750
  Data Released: False
  Global Release Data: Off
  UpdateTime: 1469
  Field Data:
    Debug: Off
    Modified Time: 1442
    Reference Count: 1
    Registered Events: (none)
    Number Of Arrays: 0
    Number Of Components: 0
    Number Of Tuples: 0
  Number Of Points: 767
  Number Of Cells: 1530
  Cell Data:
    Debug: Off
    Modified Time: 1450
    Reference Count: 1
    Registered Events:
      Registered Observers:
        vtkObserver (00000165FB8B9860)
          Event: 33
          EventName: ModifiedEvent
          Command: 00000165FB8715E0
          Priority: 0
          Tag: 1
    Number Of Arrays: 0
    Number Of Components: 0
    Number Of Tuples: 0
    Copy Tuple Flags: ( 1 1 1 1 1 0 1 1 1 1 1 1 )
    Interpolate Flags: ( 1 1 1 1 1 0 0 1 1 1 1 0 )
    Pass Through Flags: ( 1 1 1 1 1 1 1 1 1 1 1 1 )
    Scalars: (none)
    Vectors: (none)
    Normals: (none)
    TCoords: (none)
    Tensors: (none)
    GlobalIds: (none)
    PedigreeIds: (none)
    EdgeFlag: (none)
    Tangents: (none)
    RationalWeights: (none)
    HigherOrderDegrees: (none)
    ProcessIds: (none)
  Point Data:
    Debug: Off
    Modified Time: 1468
    Reference Count: 1
    Registered Events:
      Registered Observers:
        vtkObserver (00000165FB8BA3A0)
          Event: 33
          EventName: ModifiedEvent
          Command: 00000165FB8715E0
          Priority: 0
          Tag: 1
    Number Of Arrays: 2
    Array 0 name = Normals
    Array 1 name = Elevation
    Number Of Components: 4
    Number Of Tuples: 767
    Copy Tuple Flags: ( 1 1 1 1 1 0 1 1 1 1 1 1 )
    Interpolate Flags: ( 1 1 1 1 1 0 0 1 1 1 1 0 )
    Pass Through Flags: ( 1 1 1 1 1 1 1 1 1 1 1 1 )
    Scalars:
      Debug: Off
      Modified Time: 1465
      Reference Count: 1
      Registered Events: (none)
      Name: Elevation
      Data type: float
      Size: 767
      MaxId: 766
      NumberOfComponents: 1
      Information: 0000000000000000
      Name: Elevation
      Number Of Components: 1
      Number Of Tuples: 767
      Size: 767
      MaxId: 766
      LookupTable: (none)
    Vectors: (none)
    Normals:
      Debug: Off
      Modified Time: 1412
      Reference Count: 2
      Registered Events: (none)
      Name: Normals
      Data type: float
      Size: 2301
      MaxId: 2300
      NumberOfComponents: 3
      Information: 0000000000000000
      Name: Normals
      Number Of Components: 3
      Number Of Tuples: 767
      Size: 2301
      MaxId: 2300
      LookupTable: (none)
    TCoords: (none)
    Tensors: (none)
    GlobalIds: (none)
    PedigreeIds: (none)
    EdgeFlag: (none)
    Tangents: (none)
    RationalWeights: (none)
    HigherOrderDegrees: (none)
    ProcessIds: (none)
  Bounds:
    Xmin,Xmax: (-0.499052, 0.5)
    Ymin,Ymax: (-0.499763, 0.499763)
    Zmin,Zmax: (-0.5, 0.5)
  Compute Time: 1481
  Editable: false
  Number Of Points: 767
  Point Coordinates: 00000165FB8B0FF0
  PointLocator: 0000000000000000
  CellLocator: 0000000000000000
  Number Of Vertices: 0
  Number Of Lines: 0
  Number Of Polygons: 1530
  Number Of Triangle Strips: 0
  Number Of Pieces: 1
  Piece: 0
  Ghost Level: 0
  CellsBounds:
    Xmin,Xmax: (-0.499052, 0.5)
    Ymin,Ymax: (-0.499763, 0.499763)
    Zmin,Zmax: (-0.5, 0.5)
  CellsBounds Time: 1482

实例 2:把 PointIds 存储为属性、获取连通分量、实现框选操作

本实例首先创建了一个球体对象 sphere。

vtkIdFilter 是 Id 过滤器,能够从数据集中提取 Point 或 Cell 的 Id 作为数据集属性数据。我们利用它设置 sphere 的 PointIdsArrayName 为 OriginalIds。再利用 vtkDataSetSurfaceFilter 提取 sphere 的外部(多边形)表面。

vtkInteractorStyleRubberBandPick 是一个交互器。它定义:用户可以通过 R 键切换交互模式和框选模式。如果在框选模式下,用户可以通过鼠标左键画一个矩形。当鼠标释放的时候,附加的拾取器可以操作所选矩形中间的像素值。如果拾取器是 vtkAreaPicker,可以操作整个所选的矩形。

我们自定义 ExtrudeInteractorStyle 类继承自 vtkInteractorStyleRubberBandPick,重写其 OnLeftButtonUp() 方法,利用观察者模式监听鼠标左键来实现自定义功能:使用 vtkConnectivityFilter 将输入数据集中连接的单元提取到一个非结构化的网络,将选取面片网格(vtkConnectivityFilter 的输出)的点的坐标都增大为原来的 1.2 倍,可视化效果就是向外突出一块。

#include "VTKAttributeOperation.h"

#include <vtkSphereSource.h>
#include <vtkPlanes.h>
#include <vtkNamedColors.h>
#include <vtkPointData.h>
#include <vtkPointSet.h>
#include <vtkPolyData.h>
#include <vtkImplicitFunction.h>
#include <vtkIdTypeArray.h>
#include <vtkIdFilter.h>
#include <vtkConnectivityFilter.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkInteractorStyleRubberBandPick.h>
#include <vtkAreaPicker.h>
#include <vtkExtractPolyDataGeometry.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

/* vtkInteractorStyleRubberBandPick:
This interactor style allows the user to draw a rectangle in the render window by hitting 'r' and then using the left mouse button.
When the mouse button is released, the attached picker operates on the pixel in the center of the selection rectangle.
If the picker happens to be a vtkAreaPicker it will operate on the entire selection rectangle.
When the 'p' key is hit the above pick operation occurs on a 1x1 rectangle.
In other respects it behaves the same as its parent class.
*/

// vtkInteractorStyleRubberBandPick 是一个交互器
// 用户可以通过 R 键切换交互模式和框选模式
// 如果在框选模式下,用户可以通过鼠标左键画一个矩形。当鼠标释放的时候,附加的拾取器可以操作所选矩形中间的像素值
// 如果拾取器是 vtkAreaPicker,可以操作整个所选的矩形
class ExtrudeInteractorStyle : public vtkInteractorStyleRubberBandPick
{
private:
	vtkSmartPointer<vtkPolyData> m_pPolyData; // 需要处理的几何数据
	vtkSmartPointer<vtkPolyDataMapper> m_pMapper; // 用于显示框选面片的 mapper

public:
	static ExtrudeInteractorStyle* New();
	vtkTypeMacro(ExtrudeInteractorStyle, vtkInteractorStyleRubberBandPick);
	ExtrudeInteractorStyle()
	{
		m_pPolyData = vtkSmartPointer<vtkPolyData>::New();
		m_pMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	}
	void setPolyData(vtkSmartPointer<vtkPolyData> polyData)
	{
		m_pPolyData = polyData;
	}
	void setPolyDataMapper(vtkSmartPointer<vtkPolyDataMapper> polyDataMapper)
	{
		m_pMapper = polyDataMapper;
	}
	// 利用观察者模式监听鼠标左键来实现自定义功能
	virtual void OnLeftButtonUp() override
	{
		vtkInteractorStyleRubberBandPick::OnLeftButtonUp();
		if (this->CurrentMode == 1)
		{
			vtkPlanes* frustum = static_cast<vtkAreaPicker*>(this->GetInteractor()->GetPicker())->GetFrustum();
			vtkNew<vtkExtractPolyDataGeometry> extractPolyDataGeometry;
			extractPolyDataGeometry->SetInputData(m_pPolyData);
			extractPolyDataGeometry->SetImplicitFunction(frustum);
			extractPolyDataGeometry->Update();
			// vtkConnectivityFilter 将输入数据集中连接的单元提取到一个非结构化的网络
			vtkNew<vtkConnectivityFilter> connectivityFilter;
			connectivityFilter->SetInputConnection(extractPolyDataGeometry->GetOutputPort());
			connectivityFilter->SetExtractionModeToClosestPointRegion();
			connectivityFilter->SetClosestPoint(extractPolyDataGeometry->GetOutput()->GetPoint(0));
			connectivityFilter->Update();

			vtkSmartPointer<vtkPointSet> selected = connectivityFilter->GetOutput();
			// std::cout << "Selected " << selected->GetNumberOfPoints() << " points." << std::endl;
			// std::cout << "Selected " << selected->GetNumberOfCells() << " cells." << std::endl;

			vtkIdTypeArray* ids = dynamic_cast<vtkIdTypeArray*>(selected->GetPointData()->GetArray("OriginalIds"));

			vtkNew<vtkPolyData> polyNew;
			polyNew->DeepCopy(m_pPolyData);
			// 将选取面片的点的坐标都增大为原来的 1.2 倍
			for (int i = 0; i < selected->GetNumberOfPoints(); i++)
			{
				vtkIdType id = ids->GetTuple1(i);
				double pt[3];
				polyNew->GetPoint(id, pt);
				pt[0] *= 1.2;
				pt[1] *= 1.2;
				pt[2] *= 1.2;
				polyNew->GetPoints()->SetPoint(id, pt);
			}

			m_pMapper->SetInputData(polyNew);
			this->GetInteractor()->GetRenderWindow()->Render();
		}
	}
};
vtkStandardNewMacro(ExtrudeInteractorStyle);

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

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

	vtkNew<vtkRenderer> renderer;
	this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
	this->_pVTKWidget->renderWindow()->Render();

	vtkNew<vtkSphereSource> sphere;
	sphere->SetPhiResolution(21);
	sphere->SetThetaResolution(40);

	// Id 过滤器,能够从数据集中提取 Point 或 Cell 的 Id 作为数据集属性数据
	vtkNew<vtkIdFilter> idFilter;
	idFilter->SetInputConnection(sphere->GetOutputPort());
	idFilter->SetPointIdsArrayName("OriginalIds");

	// 提取外部(多边形)表面
	vtkNew<vtkDataSetSurfaceFilter> surfaceFilter;
	surfaceFilter->SetInputConnection(idFilter->GetOutputPort());
	surfaceFilter->Update();
	surfaceFilter->GetOutput()->Print(std::cout);

	vtkNew<vtkPolyDataMapper> mapper;
	mapper->SetInputConnection(surfaceFilter->GetOutputPort());
	mapper->ScalarVisibilityOff();

	vtkNew<vtkActor> actor;
	actor->SetMapper(mapper);

	renderer->AddActor(actor);

	// 基于硬件的拾取器,在用户指定的区域内选择对象
	vtkNew<vtkAreaPicker> areaPicker;
	this->_pVTKWidget->renderWindow()->GetInteractor()->SetPicker(areaPicker);

	// 创建交互器
	vtkNew<ExtrudeInteractorStyle> style;
	style->setPolyData(surfaceFilter->GetOutput());
	style->setPolyDataMapper(mapper);
	// 使用时,加入到 vtkRenderWinderInteractor 的对象中
	this->_pVTKWidget->renderWindow()->GetInteractor()->SetInteractorStyle(style);
}

VTKAttributeOperation::~VTKAttributeOperation()
{}

运行结果:

在这里插入图片描述

输出:

vtkPolyData (0000016B63085770)
  Debug: Off
  Modified Time: 1489
  Reference Count: 1
  Registered Events: (none)
  Information: 0000016B6325CBF0
  Data Released: False
  Global Release Data: Off
  UpdateTime: 1490
  Field Data:
    Debug: Off
    Modified Time: 1461
    Reference Count: 1
    Registered Events: (none)
    Number Of Arrays: 0
    Number Of Components: 0
    Number Of Tuples: 0
  Number Of Points: 762
  Number Of Cells: 1520
  Cell Data:
    Debug: Off
    Modified Time: 1482
    Reference Count: 1
    Registered Events:
      Registered Observers:
        vtkObserver (0000016B6323A1B0)
          Event: 33
          EventName: ModifiedEvent
          Command: 0000016B6327F900
          Priority: 0
          Tag: 1
    Number Of Arrays: 1
    Array 0 name = vtkIdFilter_Ids
    Number Of Components: 1
    Number Of Tuples: 1520
    Copy Tuple Flags: ( 0 1 1 1 1 0 1 1 1 1 1 1 )
    Interpolate Flags: ( 0 1 1 1 1 0 0 1 1 1 1 0 )
    Pass Through Flags: ( 0 1 1 1 1 1 1 1 1 1 1 1 )
    Scalars:
      Debug: Off
      Modified Time: 1435
      Reference Count: 2
      Registered Events: (none)
      Name: vtkIdFilter_Ids
      Data type: idtype
      Size: 1520
      MaxId: 1519
      NumberOfComponents: 1
      Information: 0000000000000000
      Name: vtkIdFilter_Ids
      Number Of Components: 1
      Number Of Tuples: 1520
      Size: 1520
      MaxId: 1519
      LookupTable: (none)
    Vectors: (none)
    Normals: (none)
    TCoords: (none)
    Tensors: (none)
    GlobalIds: (none)
    PedigreeIds: (none)
    EdgeFlag: (none)
    Tangents: (none)
    RationalWeights: (none)
    HigherOrderDegrees: (none)
    ProcessIds: (none)
  Point Data:
    Debug: Off
    Modified Time: 1487
    Reference Count: 1
    Registered Events:
      Registered Observers:
        vtkObserver (0000016B63239C70)
          Event: 33
          EventName: ModifiedEvent
          Command: 0000016B6327F900
          Priority: 0
          Tag: 1
    Number Of Arrays: 2
    Array 0 name = OriginalIds
    Array 1 name = Normals
    Number Of Components: 4
    Number Of Tuples: 762
    Copy Tuple Flags: ( 0 1 1 1 1 0 1 1 1 1 1 1 )
    Interpolate Flags: ( 0 1 1 1 1 0 0 1 1 1 1 0 )
    Pass Through Flags: ( 0 1 1 1 1 1 1 1 1 1 1 1 )
    Scalars:
      Debug: Off
      Modified Time: 1426
      Reference Count: 2
      Registered Events: (none)
      Name: OriginalIds
      Data type: idtype
      Size: 762
      MaxId: 761
      NumberOfComponents: 1
      Information: 0000000000000000
      Name: OriginalIds
      Number Of Components: 1
      Number Of Tuples: 762
      Size: 762
      MaxId: 761
      LookupTable: (none)
    Vectors: (none)
    Normals:
      Debug: Off
      Modified Time: 1376
      Reference Count: 3
      Registered Events: (none)
      Name: Normals
      Data type: float
      Size: 2286
      MaxId: 2285
      NumberOfComponents: 3
      Information: 0000000000000000
      Name: Normals
      Number Of Components: 3
      Number Of Tuples: 762
      Size: 2286
      MaxId: 2285
      LookupTable: (none)
    TCoords: (none)
    Tensors: (none)
    GlobalIds: (none)
    PedigreeIds: (none)
    EdgeFlag: (none)
    Tangents: (none)
    RationalWeights: (none)
    HigherOrderDegrees: (none)
    ProcessIds: (none)
  Bounds:
    Xmin,Xmax: (-0.5, 0.5)
    Ymin,Ymax: (-0.5, 0.5)
    Zmin,Zmax: (-0.5, 0.5)
  Compute Time: 1502
  Editable: false
  Number Of Points: 762
  Point Coordinates: 0000016B63277F80
  PointLocator: 0000000000000000
  CellLocator: 0000000000000000
  Number Of Vertices: 0
  Number Of Lines: 0
  Number Of Polygons: 1520
  Number Of Triangle Strips: 0
  Number Of Pieces: 1
  Piece: 0
  Ghost Level: 0
  CellsBounds:
    Xmin,Xmax: (-0.5, 0.5)
    Ymin,Ymax: (-0.5, 0.5)
    Zmin,Zmax: (-0.5, 0.5)
  CellsBounds Time: 1503
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值