VTK 数据处理:几何操作

news2024/11/18 13:59:58

VTK 数据处理:几何操作

  • VTK 数据处理:几何操作
    • 实例 1:使用 vtkWarpTo 向指定点发生位移
    • 实例 2:使用 vtkWarpVector 按照指定向量发生位移
    • 实例 3:使用 vtkDeformPointSet 按照框架变形

VTK 数据处理:几何操作

VTK 的几何操作主要是让模型的点坐标发生偏移。

本文章主要介绍 3 种几何操作:

  1. 使用 vtkWarpTo 向指定点发生位移
  2. 使用 vtkWarpVector 按照指定向量发生位移
  3. 使用 vtkDeformPointSet 按照框架变形

实例 1:使用 vtkWarpTo 向指定点发生位移

vtkWarpTo 类可以设置点和比例,通过朝着该点弯曲来修改点坐标,用于将数据集中的点沿着指定向量进行位移。

#include "WarpTo.h"

#include <vtkLineSource.h>
#include <vtkWarpTo.h>
#include <vtkTubeFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

WarpTo::WarpTo(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<vtkLineSource> line;
	line->SetPoint1(0, 0, 0);
	line->SetPoint2(0, 1, 0);
	line->SetResolution(20);
	line->Update();

	vtkNew<vtkTubeFilter> tubeFilter;
	tubeFilter->SetInputConnection(line->GetOutputPort());
	tubeFilter->SetRadius(0.01);
	tubeFilter->SetNumberOfSides(50);
	tubeFilter->Update();

	vtkNew<vtkWarpTo> warpTo;
	warpTo->SetInputConnection(tubeFilter->GetOutputPort());
	warpTo->SetPosition(10, 1, 0);
	warpTo->SetScaleFactor(2.0);
	warpTo->AbsoluteOn();

	vtkNew<vtkPolyDataMapper> tubeMapper;
	tubeMapper->SetInputConnection(tubeFilter->GetOutputPort());
	vtkNew<vtkPolyDataMapper> warpToMapper;
	warpToMapper->SetInputConnection(warpTo->GetOutputPort());

	vtkNew<vtkActor> tubeActor;
	tubeActor->SetMapper(tubeMapper);
	vtkNew<vtkActor> warpToActor;
	warpToActor->SetMapper(warpToMapper);

	renderer->AddActor(tubeActor);
	renderer->AddActor(warpToActor);
}

WarpTo::~WarpTo()
{
}

本实例中,我们创建了一个 vtkLineSource 类对象 line,设置它的起点和终点分别为 (0, 0, 0) 和 (0, 1, 0),并通过 vtkTubeFilter 将 line 变成一个圆柱。

创建一个 vtkWarpTo 类对象,设置点为 (10, 1, 0),偏转系数为 2。当AbsoluteOn设置为true时,位移是相对于数据集的原点进行的,这意味着所有的点都会向同一个方向偏移,即使它们在不同的位置上。但是,如果AbsoluteOn设置为false,则每个点的位移是相对于该点当前的位置进行计算的,这可能会导致每个点偏移到不同的方向,因此可能会产生非常不同的结果。

运行结果:

在这里插入图片描述

实例 2:使用 vtkWarpVector 按照指定向量发生位移

vtkWarpVector是VTK中的一个滤波器,用于根据向量数据对点进行位移。它将每个点的位置根据与该点相关联的向量进行调整,从而实现对数据集的形变操作。

该滤波器的作用是根据向量数据对点进行位移,可以用于创建各种效果,如流线、箭头、扭曲等。它可以用来可视化矢量场、流体运动、变形等应用场景。

使用vtkWarpVector滤波器时,需要提供一个向量数据集作为输入,这些向量表示了每个点的位移方向和大小。滤波器根据向量数据对每个点进行位移,从而改变其位置。位移的大小由向量的长度决定,位移的方向由向量的方向决定。

通过调整输入的向量数据,可以控制位移的强度和方向,从而实现各种不同的形变效果。这使得vtkWarpVector成为在可视化中展示矢量场和流体模拟等方面非常有用的工具。

#include "WarpVector.h"

#include <vtkPoints.h>
#include <vtkNamedColors.h>
#include <vtkProperty.h>
#include <vtkCellArray.h>
#include <vtkLine.h>
#include <vtkDoubleArray.h>
#include <vtkPointData.h>
#include <vtkWarpVector.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

WarpVector::WarpVector(QWidget* 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;

	vtkNew<vtkPoints> points;
	points->InsertNextPoint(0, 0, 0);
	points->InsertNextPoint(1, 0, 0);
	points->InsertNextPoint(2, 0, 0);
	points->InsertNextPoint(3, 0, 0);
	points->InsertNextPoint(4, 0, 0);

	vtkNew<vtkCellArray> lines;
	vtkNew<vtkLine> line;
	line->GetPointIds()->SetId(0, 0);
	line->GetPointIds()->SetId(1, 1);
	lines->InsertNextCell(line);
	line->GetPointIds()->SetId(0, 1);
	line->GetPointIds()->SetId(1, 2);
	lines->InsertNextCell(line);
	line->GetPointIds()->SetId(0, 2);
	line->GetPointIds()->SetId(1, 3);
	lines->InsertNextCell(line);
	line->GetPointIds()->SetId(0, 3);
	line->GetPointIds()->SetId(1, 4);
	lines->InsertNextCell(line);

	vtkNew<vtkPolyData> linePolyData;
	linePolyData->SetPoints(points);
	linePolyData->SetLines(lines);

	vtkNew<vtkDoubleArray> warpData;
	warpData->SetNumberOfComponents(3);
	warpData->SetName("warpData");
	double warp[] = { 0, 0, 0 };
	warp[1] = 0.0;
	warpData->InsertNextTuple(warp);
	warp[1] = 0.1;
	warpData->InsertNextTuple(warp);
	warp[1] = 0.5;
	warpData->InsertNextTuple(warp);
	warp[1] = 0.0;
	warpData->InsertNextTuple(warp);
	warp[1] = 0.3;
	warpData->InsertNextTuple(warp);

	linePolyData->GetPointData()->AddArray(warpData);
	linePolyData->GetPointData()->SetActiveVectors(warpData->GetName());

	vtkNew<vtkWarpVector> warpVector;
	warpVector->SetInputData(linePolyData);

	vtkNew<vtkPolyDataMapper> lineMapper;
	lineMapper->SetInputData(linePolyData);
	vtkNew<vtkPolyDataMapper> warpMapper;
	warpMapper->SetInputConnection(warpVector->GetOutputPort());

	vtkNew<vtkActor> lineActor;
	lineActor->SetMapper(lineMapper);
	vtkNew<vtkActor> warpActor;
	warpActor->SetMapper(warpMapper);
	warpActor->GetProperty()->SetColor(colors->GetColor3d("Gold").GetData());

	renderer->AddActor(lineActor);
	renderer->AddActor(warpActor);
}

WarpVector::~WarpVector()
{
}

本实例首先创建了一个 vtkPoints 类对象 points,里面存储了 5 个点:(0, 0, 0)、(1, 0, 0)、(2, 0, 0)、(3, 0, 0)、(4, 0, 0)、(5, 0, 0)。接着创建了一个 vtkCellArray 类 line,里面存储了 前面 5 个点相邻两两连接的 4 条线段。最后用一个 linePolyData 类对象保存了 points 和 line。

创建一个 vtkDoubleArray 类对象 warpData,里面存储了 5 个向量数据:(0, 0, 0)、(0, 0.1, 0)、(0, 0.5, 0)、(0, 0, 0)、(0, 0.3, 0)。将这个数组添加到 linePolyData 中,并设为 ActiveVectors,之后使用 vtkWarpVector 类根据向量数据(刚刚设置的 warpData)对点进行位移。它将每个点的位置根据与该点相关联的向量进行调整,从而实现对数据集的形变操作。

运行结果:

在这里插入图片描述

实例 3:使用 vtkDeformPointSet 按照框架变形

vtkDeformPointSet 的主要作用是根据一组控制点和它们的位移,对输入的点集进行形变。该类通常用于实现基于物理模型或者仿真的点集形变,比如在有限元分析中用于模拟材料的变形行为。

使用vtkDeformPointSet,可以通过指定一组控制点和它们的位移来对输入的点集进行形变。控制点的位移可以通过外部计算得到,比如基于物理模型的仿真结果或者其他形变算法的计算结果。vtkDeformPointSet会根据这些位移信息,对输入的点集进行相应的形变操作,并输出形变后的点集。

这种形变操作可以用于模拟材料的变形、动态网格变形、动画效果等各种应用场景。通过调整控制点的位移,可以实现不同形式的形变效果,从而满足各种可视化和仿真需求。

#include "DeformPointSet.h"

#include <vtkSphereSource.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkDeformPointSet.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

DeformPointSet::DeformPointSet(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->SetThetaResolution(51);
	sphere->SetPhiResolution(17);
	sphere->Update();

	double bounds[6];
	sphere->GetOutput()->GetBounds(bounds);
	// 正八面体
	vtkNew<vtkPoints> points;
	points->SetNumberOfPoints(6);
	points->SetPoint(0, bounds[0] - 0.1 * (bounds[1] - bounds[0]), (bounds[2] + bounds[3]) / 2.0, (bounds[4] + bounds[5]) / 2.0);
	points->SetPoint(1, bounds[1] + 0.1 * (bounds[1] - bounds[0]), (bounds[2] + bounds[3]) / 2.0, (bounds[4] + bounds[5]) / 2.0);
	points->SetPoint(2, (bounds[1] + bounds[0]) / 2.0, bounds[2] - 0.1 * (bounds[3] - bounds[2]), (bounds[4] + bounds[5]) / 2.0);
	points->SetPoint(3, (bounds[1] + bounds[0]) / 2.0, bounds[3] + 0.1 * (bounds[3] - bounds[2]), (bounds[4] + bounds[5]) / 2.0);
	points->SetPoint(4, (bounds[1] + bounds[0]) / 2.0, (bounds[2] + bounds[3]) / 2.0, bounds[4] - 0.1 * (bounds[5] - bounds[4]));
	points->SetPoint(5, (bounds[1] + bounds[0]) / 2.0, (bounds[2] + bounds[3]) / 2.0, bounds[5] + 0.1 * (bounds[5] - bounds[4]));
	vtkNew<vtkCellArray> tris;
	tris->InsertNextCell(3);
	tris->InsertCellPoint(2); tris->InsertCellPoint(0); tris->InsertCellPoint(4);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(1); tris->InsertCellPoint(2); tris->InsertCellPoint(4);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(3); tris->InsertCellPoint(1); tris->InsertCellPoint(4);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(0); tris->InsertCellPoint(3); tris->InsertCellPoint(4);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(0); tris->InsertCellPoint(2); tris->InsertCellPoint(5);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(2); tris->InsertCellPoint(1); tris->InsertCellPoint(5);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(1); tris->InsertCellPoint(3); tris->InsertCellPoint(5);
	tris->InsertNextCell(3);
	tris->InsertCellPoint(3); tris->InsertCellPoint(0); tris->InsertCellPoint(5);
	vtkNew<vtkPolyData> regularOctahedronPolyData;
	regularOctahedronPolyData->SetPoints(points);
	regularOctahedronPolyData->SetPolys(tris);

	// vtkDeformPointSet 根据一组控制点和它们的位移,对输入的点集进行形变
	vtkNew<vtkDeformPointSet> deformPointSet;
	deformPointSet->SetInputConnection(sphere->GetOutputPort());
	deformPointSet->SetControlMeshData(regularOctahedronPolyData); // 把正八面体作为控制网格
	deformPointSet->Update();

	double controlPoint[3];
	points->GetPoint(5, controlPoint);
	points->SetPoint(5, controlPoint[0], controlPoint[1], bounds[5] + 0.8 * (bounds[5] - bounds[4]));
	points->Modified();

	vtkNew<vtkPolyDataMapper> deformedSphereMapper;
	deformedSphereMapper->SetInputConnection(deformPointSet->GetOutputPort());
	vtkNew<vtkPolyDataMapper> regularOctahedronMapper;
	regularOctahedronMapper->SetInputData(regularOctahedronPolyData);

	vtkNew<vtkActor> deformedSphereActor;
	deformedSphereActor->SetMapper(deformedSphereMapper);
	vtkNew<vtkActor> regularOctahedronActor;
	regularOctahedronActor->SetMapper(regularOctahedronMapper);

	renderer->AddActor(deformedSphereActor);
	renderer->AddActor(regularOctahedronActor);
}

DeformPointSet::~DeformPointSet()
{
}

本实例创建了一个球体和一个正八面体。通过创建一个 vtkDeformPointSet 类,把球体作为输入,把正八面体作为控制网格。程序修改了正八面体的一个点的坐标,vtkDeformPointSet 类根据一组控制点(正八面体的点集)和它们的位移,对输入的点集(球体)进行形变。

运行结果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统思考—战略沙盘推演咨询服务

今日与JSTO团队一起学习了《战略沙盘推演咨询服务》。通过沙盘体验&#xff0c;我深刻感受到组织与战略就像一张皮的正反两面。在转型过程中&#xff0c;即使战略非常明确&#xff0c;团队成员由于恐惧和顾虑&#xff0c;往往不愿意挑战新的业务&#xff0c;从而难以实现战略目…

PHP框架 Laravel

现在因为公司需求&#xff0c;需要新开一个Laravel框架的项目&#xff0c;毫无疑问&#xff0c;我又被借调过去了&#xff0c;最近老是被借调&#xff0c;有点阴郁&#xff0c;不过反观来看&#xff0c;这也是好事&#xff0c;又可以复习和巩固一下自己的知识点&#xff0c;接下…

Android 生成正式版密钥库 KeyStore

步骤1&#xff1a;打开生成正式版密钥库设置 点击 Build 菜单&#xff0c;选择 Generate Signed App Bundle or APK&#xff1a; 这是打开后的样子&#xff1a; 步骤2&#xff1a;选择 APK Android App Bundle 是用于上架 Google Play 商店的。 正常情况下选择 APK。 选择…

Rust 程序设计语言学习——常见集合:Vector String Map

Rust 中常见的集合包括 Vector&#xff08;列表&#xff09;、String&#xff08;字符串&#xff09;和 Map&#xff08;键值对&#xff09;。 Vec<T>&#xff0c;也被称为 vector。vector 允许我们在一个单独的数据结构中储存多于一个的值&#xff0c;它在内存中彼此相邻…

Java之Writer类:探索Java中的输出流

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

拿捏数据结构-top_k问题

top_k问题时间复杂度的计算 这里提前说明&#xff0c;时间复杂度的计算的目的是来计算向上调整的更优还是向下调整更优&#xff0c;从肉眼看的话向下调整优于向上调整&#xff0c;接下来我们进行时间复杂度的计算。 此时我们会用到等比数列求和以及裂项相消 如图 首先我们假设求…

【物联网实战项目】STM32C8T6+esp8266/mqtt+dht11+onenet+uniapp

一、实物图 前端uniapp效果图&#xff08;实现与onenet同步更新数据&#xff09; 首先要确定接线图和接线顺序&#xff1a; 1、stm32c8t6开发板连接stlinkv2下载线 ST-LINK V2STM323.3V3.3VSWDIOSWIOSWCLKSWCLKGNDGND 2、ch340串口连接底座&#xff08;注意RXD和TXD的连接方式…

Spring Boot集成shiro之使用redis缓存demo

1.背景 上次发了这篇文章《Spring Boot集成Shiro快速入门Demo》后&#xff0c;有网友“just.blue”后台反馈集成redis有点问题&#xff0c;今天特地把集成过程发出来 2.为什么要使用cache 用来减轻数据库的访问压力&#xff0c;从而提升查询效率。 3.Shiro使用Redis做缓存 …

Go 实现 WebSocket 的双向通信

在Go语言中实现WebSocket的双向通信通常需要使用第三方库&#xff0c;其中 gorilla/websocket 是一个非常流行和广泛使用的库。 1、安装 go get github.com/gorilla/websocket 2、编写WebSocket服务器代码 package mainimport ("fmt""github.com/gorilla/we…

AlibabaCloud(阿里云)支付方式介绍,使用虚拟卡支付阿里云

一、支付方式 二、 添加支付方式 点击添加支付方式按钮&#xff0c;您将进入添加支付方式流程。选择您偏好的支付方式&#xff0c;按页面指导进行添加即可。 1、信用卡 可以使用Fomepay的信用进行支付&#xff0c;点击获取 依次输入您银行卡的卡号、有效期、安全码&#xff…

实现一个简单的 Google Chrome 扩展程序

目录 &#x1f9ed; 效果展示 # 图示效果 a. 拓展程序列表图示效果&#xff1a; b. 当前选项卡页面右键效果&#xff1a; c. 拓展程序消息提示效果&#xff1a; &#x1f4c7; 项目目录结构 # 说明 # 结构 # 文件一览 ✍ 核心代码 # manifest.json # background.j…

JWT-登录后下发令牌

后端 写一个jwt工具类&#xff0c;处理令牌的生成和校验&#xff0c;如&#xff1a; 响应数据样例&#xff1a; 前端要做的&#xff1a;

Nginx文件解析漏洞复现:CVE-2013-4547

漏洞原理 CVE-2013-4547漏洞是由于非法字符空格和截止符导致Nginx在解析URL时的有限状态机混乱&#xff0c;导致攻击者可以通过一个非编码空格绕过后缀名限制。假设服务器中存在文件1. jpg&#xff0c;则可以通过改包访问让服务器认为访问的为PHP文件。 漏洞复现 开启靶场 …

均值算法详细教程(个人总结版)

背景 均值算法&#xff0c;也称为平均值算法&#xff0c;是统计分析中的基本方法之一。它通过求取一组数据的平均值来概括数据的集中趋势。在数据分析、机器学习、信号处理等领域&#xff0c;均值算法被广泛应用。 均值的种类 算术均值&#xff08;Arithmetic Mean&#xff…

手把手教你快速玩转香橙派AIPro

什么是香橙AIPro&#xff1f; OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持…

设计模式 19 模板模式 Template Pattern

设计模式 19 模板模式 Template Pattern 1.定义 模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤的具体实现延迟到子类中。在模板模式中&#xff0c;定义了一个抽象类&#xff0c;其中包含了一个…

2024.5组队学习——MetaGPT(0.8.1)智能体理论与实战(中):订阅智能体OSS实现

传送门&#xff1a; 《2024.5组队学习——MetaGPT&#xff08;0.8.1&#xff09;智能体理论与实战&#xff08;上&#xff09;&#xff1a;MetaGPT安装、单智能体开发》《2024.5组队学习——MetaGPT&#xff08;0.8.1&#xff09;智能体理论与实战&#xff08;下&#xff09;&…

2024年电工杯高校数学建模竞赛(A题) 建模解析| 园区微电网风光储协调优化配置

问题重述及方法概述 问题1&#xff1a;各园区独立运营储能配置方案及其经济性分析 经济性分析采用成本-效益分析方法&#xff0c;计算购电量、弃风弃光电量、总供电成本和单位电量平均供电成本等指标。 问题2&#xff1a;联合园区储能配置方案及其经济性分析 经济性分析采用成…

《Ai企业知识库》-rasa X安装使用

背景&#xff1a; Rasa X 是一个为构建、改进和管理对话式AI助手而设计的工具。它是Rasa开源机器学习框架的一个扩展&#xff0c;旨在实现“对话驱动开发”&#xff08;Conversation-Driven Development&#xff09;。Rasa X 主要特点包括&#xff1a; 交互式学习&#xff1a;…

百度智能小程序源码系统 关键词推广优化排名高 带完整的安装代码包以及搭建教程

系统概述 百度智能小程序源码系统是一套完整的解决方案&#xff0c;为用户提供了创建、发布和管理智能小程序的平台。它基于百度平台的先进技术&#xff0c;确保小程序在运行和展示方面具有出色的表现。 代码示例 系统特色功能 1.关键词推广优化&#xff1a;系统内置了强大的…