VTK随笔三:坐标系统、空间变换、VTK管线、VTK智能指针

news2024/11/24 10:31:07

一、坐标系统 

  • Model坐标系统:定义模型时所采用的坐标系统,通常是局部的笛卡尔坐标系。
  • World坐标系统:是放置Actor的三维空间坐标系,Actor(vtkActor类)其中的一个功能就是负责将模型从Model坐标系统变换到World坐标系统。每一个模型可以定义自己的Model坐标系统,但World坐标系只有一个,每一个Actor必须通过放缩、旋转、平移等操作将Model坐标系变换到World坐标系。World坐标系同时也是相机和灯光所在的坐标系统。
  • View坐标系统:表示的是相机所看见的坐标系统。X、Y、Z轴取值为[-1, 1],X、Y值表示像平面上的位置,Z值表示到相机的距离。相机负责将World坐标系变换到View坐标系。
  • Display坐标系统:与View坐标系统类似,但是各坐标轴的取值不是[-1, 1],而是使用屏幕的像素值。屏幕上显示的不同窗口的大小会影响View坐标系的坐标值[-1, 1]到Display坐标系的映射。可以把不同的渲染场景放在同一个窗口进行显示,例如,在一个窗口里,分为左右两个渲染场景,这左右的渲染场景(vtkRenderer)就是不同的视口(Viewport)。

示例Viewport实现将一个窗口分为4个视口:

#include <QApplication>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkActor.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkConeSource.h>
#include <vtkCubeSource.h>
#include <vtkCylinderSource.h>
#include <vtkSphereSource.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 创建四个不同形状的源对象
    vtkNew<vtkConeSource> cone;
    vtkNew<vtkCubeSource> cube;
    vtkNew<vtkCylinderSource> cylinder;
    vtkNew<vtkSphereSource> sphere;

    // 创建四个Mapper对象,将源对象连接到Mapper上
    vtkNew<vtkPolyDataMapper> coneMapper;
    coneMapper->SetInputConnection(cone->GetOutputPort());
    vtkNew<vtkPolyDataMapper> cubeMapper;
    cubeMapper->SetInputConnection(cube->GetOutputPort());
    vtkNew<vtkPolyDataMapper> cylinderMapper;
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
    vtkNew<vtkPolyDataMapper> sphereMapper;
    sphereMapper->SetInputConnection(sphere->GetOutputPort());

    // 创建四个Actor对象,并将Mapper连接到Actor上
    vtkNew<vtkActor> coneActor;
    coneActor->SetMapper(coneMapper);
    vtkNew<vtkActor> cubeActor;
    cubeActor->SetMapper(cubeMapper);
    vtkNew<vtkActor> cylinderActor;
    cylinderActor->SetMapper(cylinderMapper);
    vtkNew<vtkActor> sphereActor;
    sphereActor->SetMapper(sphereMapper);

    // 创建四个Renderer对象,并设置每个Renderer的背景颜色和视口
    vtkNew<vtkRenderer> renderer1;
    renderer1->AddActor(coneActor);
    renderer1->SetBackground(1.0,0.0,0.0);
    renderer1->SetViewport(0.0,0.0,0.5,0.5);
    vtkNew<vtkRenderer> renderer2;
    renderer2->AddActor(cubeActor);
    renderer2->SetBackground(0.0,1.0,0.0);
    renderer2->SetViewport(0.5,0.0,1.0,0.5);
    vtkNew<vtkRenderer> renderer3;
    renderer3->AddActor(cylinderActor);
    renderer3->SetBackground(0.0,0.0,1.0);
    renderer3->SetViewport(0.0,0.5,0.5,1.0);
    vtkNew<vtkRenderer> renderer4;
    renderer4->AddActor(sphereActor);
    renderer4->SetBackground(1.0,1.0,0.0);
    renderer4->SetViewport(0.5,0.5,1.0,1.0);

    // 创建RenderWindow对象,并将四个Renderer添加到RenderWindow中
    vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
    renderWindow->AddRenderer(renderer1);
    renderWindow->AddRenderer(renderer2);
    renderWindow->AddRenderer(renderer3);
    renderWindow->AddRenderer(renderer4);
    QVTKOpenGLNativeWidget w;
    w.setRenderWindow(renderWindow);

    w.show();
    return a.exec();
}

效果如下:

vtkCoordinate可以用来表示坐标系统,其内部提供了函数接口来定义坐标系统: 

SetCoordinateSystemToDisplay()
SetCoordinateSystemToNormalizedDisplay()
SetCoordinateSystemToViewport()
SetCoordinateSystemToNormalizedViewport()
SetCoordinateSystemToView()
SetCoordinateSystemToWorld()

另外,该类还实现这些坐标系统之间的转换,例如下述代码实现了归一化窗口坐标与窗口坐标之间的转换: 

vtkNew<vtkCoordinate> coordinate;
coordinate->SetCoordinateSystemToNormalizedDisplay();
coordinate->SetValue(.5, .5, 0);	// 屏幕中心

int* val = coordinate->GetComputedDisplayValue(renderer);	// 窗口坐标转换

二、空间变换 

        在三维空间里定义的三维模型,最后显示时都是投影到二维平面,比如在屏幕上显示三维到二维的投影包括透视投影(PerspectiveProjection)和正交投影(Orthogonal Projection)。正交投影也叫平行投影。

        VTK里与空间变换有关的类有vtkTransform2D,vtkTransform,vtkPerspectiveTransform,vtkGeneralTransform,vtkTransformFilter,vtkMatrix4×4等。例如下面代码实现了vtkActor对象的空间变换: 

vtkNew<vtkTransform> transform;
transform->PostMultiply();	// 设置右乘计算变换矩阵。
transform->RotateZ(40);	//旋转
transform->Translate(10, 0, 0);	// 平移
cylinderActor->SetUserTransform(transform);

 三、VTK管线

        vtkProp、vtkAbstractMapper、vtkProperty、vtkCamera、vtkLight、vtkRenderer、vtkRendererWindow、vtkRenderWindowInteractor、vtkTransform、vtkLookupTable等等类都是与数据显示或渲染相关的,它们构成了VTK的渲染引擎(Rendering Engine)。渲染引擎主要负责数据的可视化表达,是VTK里的两个重要概念之一,而另一个重要概念就是可视化管线(Visualization Pipeline)

        可视化管线是指用于获取或创建数据、处理数据以及把数据写入文件或者把数据传递给渲染引擎进行显示,这样的一种结构在VTK里就称为可视化管线。数据对象(Data Object)、处理对象(Process Object)和数据流方向(Direction of Data Flow)是可视化管线的三个要素。每个VTK程序都会有可视化管线存在。

 

        Source是指用于创建数据(如vtkCylinderSource)或者读取数据(如vtkBMPReader、vtkStructuredPointsReader等)类的统称,即VTK的数据源。Source输出的数据作为Filter的输入,经Filter处理以后(可以经过多个Filter处理),生成新的数据。Filter的输出可以直接写入文件,或者经Mapper变换后传入渲染引擎进行渲染、显示,结束可视化管线。上图的箭头方向即为VTK里数据流流动的方向。

        可视化管线的三要素分别为数据对象、处理对象和数据流方向,Source、Filter和Mapper一起构成了处理对象,它们的区别是基于数据流的初始化、维持和终止。根据数据的生成方式,Source可以分为程序源对象(Procedural,如vtkCylinderSource,通过程序代码生成相关的数据)和读取源对象(Reader,如vtkBMPReader,从外部文件中导入数据)。

四、智能指针

   智能指针会自动管理引用计数的增加与减少。

c++中智能指针:

1:unique_ptr :这是一种独占式的智能指针;确保在其使用的生命周期内只有一个指针可以指向被

分配的对象;当其被销毁的时候,其管理的对象也被销毁。

2:share_ptr : 允许多个智能指针共享对同一资源的所有权。它使用引用计数来跟踪资源的引用次数,当最后一个std::shared_ptr离开作用域时,资源会被释放

3:weak_ptr : 允许多个智能指针共享对同一资源的所有权。它使用引用计数来跟踪资源的引用次数,当最后一个std::shared_ptr离开作用域时,资源会被释放。

        VTK中智能指针类为vtkSmartPointer。VTKSmartPointer是一个模板类,继承自VTKSmartPointerBase类。VTKSmartPointerBase中定义了一个vtkObjectBase类型的指针对象Object,用于存储智能指针中实际生成的对象。智能指针定义为:

vtkSmartPointer<vtkCamera> camera =  vtkSmartPointer<vtkCamera>::New();   //引用计数为1

        VTKSmartPointer中定义了静态函数New()来生成一个智能指针对象。该函数的核心在于:会根据模板参数类型来生成一个对象,并将其保存在基类VTKSmartPointerBase的成员变量Object中。

        VTKSmartPointer中重载了“->”操作符,返回实际模板参数类型的对象,因此可以方便地访问对象的成员函数,如camera->setFocusPosition(0,0,0)。

        VTKSmartPointer重载了“=”操作符,可以在VTKSmartPointer对象之间进行赋值。在赋值过程中,VTKSmartPointer会自动控制其内部对象指针Object的引用计数加1。

例如:

vktSmartPointer<vtkCamera> camera1 =vtkSmartPointer<vtkCamera>::New();
vtkSmartPointer<vtkCamera> camera2 = camera1;

        需要注意的是,此时camera1和camera2的引用计数都等于2。
        过程为:首先camera1的vtkCamera对象Object调用Register()函数,自动将引用计数加1,然后将camera2的Object指向camera1的Object对象。
        当一个智能指针对象的生命周期结束时,会自动调用其析构函数释放内存。在析构函数中会调用其内部对象Object的UnRegister()函数修改引用计数。如果此时的引用计数为0,Object对象会自动释放内存。

 

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

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

相关文章

python动画:实现贝塞尔曲线【bezier】

贝塞尔曲线在计算机图形学中用于绘制形状、用于 CSS 动画和许多其他地方。它们是一件非常简单的事情&#xff0c;值得学习一次&#xff0c;然后在矢量图形和高级动画的世界中感到舒适。 一.控制点 贝塞尔曲线由控制点可能有 2、3、4 或更多。 例如&#xff0c;二次贝塞尔曲线…

基于java教师课堂教学质量评价系统设计与实现

课题背景 高等学校的根本任务是培养人才&#xff0c;课堂教学是高校完成人才培养的重要环节&#xff0c;因此&#xff0c; 教师教学质量的高低对学生掌握和运用知识的程度有着密不可分的作用&#xff0c;为了保证教师的教学质量&#xff0c;教学评价成为了各高校衡量教师教学质…

大数据-92 Spark 集群 SparkRDD 原理 Standalone详解 ShuffleV1V2详解 RDD编程优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

盘古信息IMS MCM制造协同管理系统:为中小企业数字化转型量身打造的数字化方案

近年来&#xff0c;全球经济的不稳定性&#xff0c;给中小企业的经营和发展带来了巨大的挑战。为提升企业竞争力&#xff0c;中小企业纷纷谋求数字化转型路径&#xff0c;优化生产流程、提高运营效率、降低生产成本&#xff0c;以应对变幻莫测的市场环境。IMS MCM是盘古信息为广…

go中 panicrecoverdefer机制

go的defer机制-CSDN博客 常见panic场景 数组或切片越界&#xff0c;例如 s : make([]int, 3); fmt.Println(s[5]) 会引发 panic: runtime error: index out of range空指针调用&#xff0c;例如 var p *Person; fmt.Println(p.Name) 会引发 panic: runtime error: invalid m…

IT 人员配置的演变趋势:2024 年上半年的见解

随着我们深入研究 2024 年的动态格局&#xff0c;IT 人员配置领域在前六个月见证了几个值得注意的趋势和变化。 这些发展不仅反映了企业不断变化的需求&#xff0c;也凸显了技术对劳动力动态的变革性影响。 以下是在这个关键年份上半年塑造 IT 人员配置的一些关键趋势的详细介…

Python办公自动化smtplib实现自动发送邮件

学好python自动化&#xff0c;走遍天下都不怕&#xff01;&#xff01; 今天主要学习如何利用python自动化分析处理数据并以附件形式发送邮箱。需要安装配置python的运行环境&#xff0c;以及电脑支持Excel文件&#xff0c;有可以正常使用的邮箱。还需要用到python的第三方模块…

剧本杀门店预约小程序,提高消费者体验

当下&#xff0c;剧本杀行业一直处于活跃的状态&#xff0c;不管是线下聚会还是休闲娱乐&#xff0c;剧本杀游戏都是消费者的选择&#xff0c;剧本杀市场具有非常大的发展前景。 剧本杀门店预约系统是一个高效、便捷的游戏预约方式&#xff0c;能够帮助消费者便捷预约&#xf…

基于ssm的爱心捐赠管理系统的设计与实现(论文+源码)_kaic

摘 要 在互联网高速发展的现在&#xff0c;许多的办公与应用从传统的实体办理变为了在线处理。网购与网淘商品的浏览也从大街小巷变为了在线预览&#xff0c;从而使网上用户更好地对物品产生客观、全面立体的认知&#xff0c;并且对物品的对比也更加的省时省力。 爱心捐赠管…

一个简单的springboot项目(有源码)

开发一个springboot项目 代码迭代整合工具 gitee建模意义程序处理方式开发功能的步骤web服务网络状态码 web应用的开发分层springboot的作用 springboot框架搭建框架中各组件作用框架的演变如何提取hive中的表结构创建springboot 工程的引导模版 要选择aliyun &#xff0c;否则…

java ssl使用自定义证书或忽略证书

1.证书错误 Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 2.生成客户端证书 openssl x509 -in <(openssl s_client -connect 192.168.11.19:8101 -prexit 2>/dev/null) -ou…

linux neo4j 切换知识图谱

neo4j 安装 linux neo4j的安装可以浏览这篇文章&#xff1a; ubuntu sudo apt-get install neo4j 配置安装与设置远程访问 引言 如果你是window用户&#xff0c;直接下载桌面版进行安装与使用即可&#xff1b; 我有一台linux的服务器&#xff0c;想部署在上面&#xff0c;不…

UE5.4内容示例(5)UI_CommonUI - 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例&#xff0c;可以用此熟悉一遍UE5的功能 UI_CommonUI可以看这个视频学习&#xff0c;此插件处于Beta状态&#xff0c;应用UI游戏方面&#xff0c;支持手柄等多输入端…

打饭-GYM

打饭 我还不信了&#xff0c;手动模拟一遍 再来了好看一点的图 ji12345a[i]21341120x3f0x3f0x3f0x3f0x3f114220x3f0x3f0x3f0x3f103520x3f0x3f0x3f0x3f9min(332,42)4020x3f0x3f0x3f8min(332,35)min(332,40)3190x3f0x3f7min(262,33)332490x3f0x3f6min(172,33)3120x3f0x3f0x3f5min…

【前端基础篇】JavaScript基础介绍

文章目录 前言初始JavaScriptJavaScript是什么发展历史JavaScript和HTML和CSS之间的关系JavaScript的运行过程JavaScript的组成 JavaScript的书写形式行内式内嵌式外部式注释 输入输出基础语法变量数据类型 运算符 JavaScript对象对象new关键字 常用对象数组创建数组数组操作函…

电影票api接口对接开发过程中需要注意什么?

电影票API接口对接过程需要考虑以下几个关键点&#xff1a; 1.了解API接口基础&#xff1a; 获取接口文档&#xff0c;理解其结构、请求方式、参数和返回数据格式。 2.接入流程&#xff1a; 使用API密钥或令牌进行身份验证。利用沙箱环境无风险测试。选择合适的编程语言实现…

Centos LVM磁盘合并方法

Centos LVM磁盘合并方法 使用fdisk -l命令查看机器增加了2块物理磁盘&#xff0c;一块40G另一块50G 需要将这两块盘的空间合并在一起&#xff0c;而且还需要动态扩展即在不关机的情况下操作 使用pvcreate将两块新增的物理磁盘加入物理卷 [rootlocalhost ~]# pvcreate /dev/sdb…

6G网络的关键技术、应用前景与挑战并存的科技征途

移动通信技术正以前所未有的速度迭代更新&#xff0c;而6G技术的研发与商用化进程渐渐成为了当前科技领域的热点与焦点。在5G技术尚未完全普及的今天&#xff0c;全球各国已纷纷将目光投向了更加充满想象的6G网络时代。本文将探讨全球6G研发的最新进展&#xff0c;特别是欧盟与…

Webots与ROS1、ROS2接口变迁-2024-

三大免费仿真器CoppeliaSim、Gazebo和Webots。 Gazebo接口总结&#xff1a; Gazebo与ROS1、ROS2接口变迁-2005-2024--CSDN博客 缺点&#xff1a;版本绑定策略 早期webots版本和ros版本绑定 后期&#xff0c;webots接口最新版本和ros特定版本最匹配。 例如&#xff1a; 最好按…

Ubuntu 中 SSH 服务的配置与原理详解

目录 1. 基本知识2. 配置步骤 1. 基本知识 一种用于在不安全的网络上安全登录和执行命令的协议 通过加密的方式保护通信数据&#xff0c;确保在传输过程中不被窃取或篡改 SSH 常用于远程登录服务器、传输文件以及执行命令 SSH 原理 公钥和私钥&#xff1a;SSH 使用公钥加密来…