VTK 的可视化方法:Glyph

VTK 的可视化方法:Glyph

  • 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/589126.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

25 JavaScript学习:var let const

JavaScript全局变量 JavaScript中全局变量存在多种情况和定义方式&#xff0c;下面详细解释并提供相应的举例&#xff1a; 使用var关键字声明的全局变量&#xff1a; var globalVar "我是全局变量";未使用var关键字声明的变量会成为全局变量&#xff08;不推荐使用&…

【前端】-【防止接口重复请求】

文章目录 需求实现方案方案一方案二方案三 需求 对整个的项目都做一下接口防止重复请求的处理 实现方案 方案一 思路&#xff1a;通过使用axios拦截器&#xff0c;在请求拦截器中开启全屏Loading&#xff0c;然后在响应拦截器中将Loading关闭。 代码&#xff1a; 问题&…

(刷题记录2)随机链表的复制

[刷题记录2]随机链表的复制 题目信息&#xff1a;题目思路(环境来自力扣OJ的C语言)&#xff1a;复杂度&#xff1a;代码和解释&#xff1a;1.遍历一遍原链表的同时&#xff0c;在每个原节点后面插入一个相同的新节点&#xff0c;共插入 n 个新节点。2.利用两者联系&#xff0c;…

神奇的Vue3 - 组件探索

神奇的Vue3 第一章 神奇的Vue3—基础篇 第二章 神奇的Vue3—Pinia 文章目录 神奇的Vue3了解组件一、注册组件1. 全局注册​2. 局部注册3. 组件命名 二、属性详解1. Props&#xff08;1&#xff09;基础使用方法&#xff08;2&#xff09;数据流向&#xff1a;单项绑定原则&…

ThreeJS:Mesh网格与三维变换

Mesh网格 ThreeJS中&#xff0c;Mesh表示基于以三角形为多边形网格(polygon mesh)的物体的类&#xff0c;同时也作为其它类的基类。 通过Mesh网格&#xff0c;我们可以组合Geometry几何体与Material材质属性&#xff0c;在3D世界中&#xff0c;定义一个物体。例如&#xff1a;之…

vue2(4)之scoped解决样式冲突/组件通信/非父子通信/ref和$refs/异步更新/.sync/事件总线/provide和inject

vue2 一、学习目标1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09;2.组件通信3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09;4.进阶语法 二、scoped解决样式冲突**1.默认情况**&#xff1a;2.代码演示3.scoped原理4.总结 三、data必须是一个函数…

Copilot Venture Studio創始合伙人楊林苑確認出席“邊緣智能2024 - AI開發者峰會”

隨著AI技術的迅猛發展&#xff0c;全球正逐步進入邊緣計算智能化與分布式AI深度融合的新時代&#xff0c;共同書寫著分布式智能創新應用的壯麗篇章。邊緣智能&#xff0c;作為融合邊緣計算和智能技術的新興領域&#xff0c;正逐漸成為推動AI發展的關鍵力量。借助分布式和去中心…

由于找不到mfc140u.dll,无法继续执行的多种解决方法

在我们日常与计算机的密切互动中&#xff0c;或许不少用户都曾遇到过这样一个棘手的问题&#xff1a;系统突然弹出一个提示窗口&#xff0c;告知我们“找不到mfc140u.dll文件”。这个文件是Microsoft Foundation Class&#xff08;MFC&#xff09;库的一部分&#xff0c;用于支…

提升编码技能:学习如何使用 C# 和 Fizzler 获取特价机票

引言 五一假期作为中国的传统节日&#xff0c;也是旅游热门的时段之一&#xff0c;特价机票往往成为人们关注的焦点。在这个数字化时代&#xff0c;利用爬虫技术获取特价机票信息已成为一种常见的策略。通过结合C#和Fizzler库&#xff0c;我们可以更加高效地实现这一目标&…

20240502在WIN10下给X99平台上的M6000显卡安装驱动程序

20240502在WIN10下给X99平台上的M6000显卡安装驱动程序 2024/5/2 9:32 人工智能计算领域的领导者 | NVIDIA https://www.nvidia.cn/ C:\NVIDIA\DisplayDriver\552.22\Win11_Win10-DCH_64\International IMPORTANT NOTICE -- READ CAREFULLY: -------------------------------…

pmp培训机构哪个比较好,求推荐-

寻找一个自己认为比较好的PMP培训机构千万不要盲目&#xff0c;先在网上看看大家都推荐什么&#xff0c;看一下各个机构的老学员反馈&#xff0c;这些对我们的选择有非常大的帮助&#xff0c;最起码有了一些风评上的参考&#xff0c;现状就是目前线上机构的竞争比较大&#xff…

c语言从入门到函数速成(1)

温馨提醒&#xff1a;本篇文章适合人群&#xff1a;刚学c又感觉那个地方不怎么懂的同学以及以及学了一些因为自身原因停学一段时间后又继续学c的同学 好&#xff0c;正片开始。 主函数 学c时最先学的是我们c语言程序的主体函数&#xff0c;c的主函数有两种写法&#xff0c;这…

【JavaEE】Thread的方法和属性

文章目录 1、Thread的常见构造方法2、Thread的几个常见属性2.1 ID2.2 名称2.3 状态2.4 优先级2.5 是否后台线程2.6 是否存活2.7 是否被中断 3.补充说明3.1 Thread.sleep()的作用3.2 Thread.sleep()的异常处理方式 1、Thread的常见构造方法 方法说明Thread()创建线程对象Thread…

动态规划-子序列问题1

文章目录 1. 最长递增子序列&#xff08;300&#xff09;2. 摆动序列&#xff08;376&#xff09;3. 最长递增子序列的个数&#xff08;673&#xff09;4. 最长数对链&#xff08;646&#xff09; 1. 最长递增子序列&#xff08;300&#xff09; 题目描述&#xff1a; 状态表…

Linux 进程间通信之命名管道

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux知识分享⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; 目录 前言 命名管道 创建一个命名管道 …

LeetCode题练习与总结:删除排序链表中的重复元素--83

一、题目描述 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输…

袁庭新ES系列17节|Spring Data Elasticsearch基础

前言 为了简化对Elasticsearch的操作Spring Data提供了Spring Data Elasticsearch。Spring Data Elasticsearch是Spring Data技术对Elasticsearch原生API封装之后的产物&#xff0c;它通过对原生API的封装&#xff0c;使得程序员可以简单的对Elasticsearch进行各种操作。接下来…

InfluxDB安装使用介绍

1.介绍 InfluxDB是一个由InfluxData开发的开源时序型数据。它由Go写成&#xff0c;着力于高性能地查询与存储时序型数据。InfluxDB被广泛应用于存储系统的监控数据&#xff0c;IoT行业的实时数据等场景。 2.对常见关系型数据库&#xff08;MySQL&#xff09;的基础概念对比 1…

满上! —— 十年之约#22(ROI 48%)

原创 | 刘教链 空头在忍耐了很久之后&#xff0c;趁五一劳动节东方放假发动突袭&#xff0c;把BTC&#xff08;比特币&#xff09;打到6万刀以下。这使得我们终于终结了7个月七连涨的趋势&#xff0c;确定4月以收跌结束。 4月开盘70k&#xff0c;最高72.8k&#xff0c;最低59.6…

CPU卡园区码分析计算,根据卡号计算外部密码

生活中我们可能遇到这种情况&#xff0c;比如家里的门禁卡丢失了&#xff0c;拿着家里人的去街上 复制&#xff0c;结果对方说无法复制&#xff0c;因为这种卡是CPU卡的一种&#xff0c;必须知道园区码才可以成功复制&#xff0c;这个时候&#xff0c;我们就需要请出我们的战神…