VTK编程指南<五>:VTK中的坐标系统、空间变换及VTK矩阵详解

1、坐标系统

  计算机图形学里常用的坐标系统主要有 4 种,分别是 Model 坐标系统、World 坐标系统、View坐标系统和 Display坐标系统(这些名词在不同的书里的中文表述均有所差别,所以直接使用英文名词表示),此外还有两种表示坐标点的方式:以屏幕像素值为单位和归一化坐标值(各坐标轴取值范围为[-1,1])。它们之间的关系如图 所示。

  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个视口,用vtkRenderer::SetViewport()来设置视口的范围(取值为[0,1]):

renderer1->SetViewport(0.0,0.0,0.5,0.5);
renderer2->SetViewport(0.5,0.0,1.0,0.5);
renderer3->SetViewport(0.0,0.5,0.5,1.0);
renderer4->SetViewport(0.5,0.5,1.0,1.0);

  在VTK里,Model坐标系统用得比较少,其他三种坐标系统经常使用。它们之间的变换则是由类 vtkCoordinate 进行管理的。根据坐标值的单位、取值范围等不同,可以将坐标系统细分为如下几类。

  • DISPLAY——X、Y轴的坐标取值为渲染窗口的像素值。坐标原点位于渲染窗口的左下角,这个对于VTK里的所有二维坐标系统都是一样的,且VTK里的坐标系统都是采用右手坐标系。
  • NORMALIZED DISPLAY——X、Y 轴坐标取值范围为[0,1],跟 DISPLAY一样,也是定义在渲染窗口里的。
  • VIEWPORT——X、Y的坐标值定义在视口或者渲染器(Renderer)里。
  • NORMALIZED VIEWPORT——X、Y 坐标值定义在视口或渲染器里,取值范围为[0,1]。
  • VIEW ——X、Y、Z 坐标值定义在相机所在的坐标系统里,取值范围为[-1,1],Z值表示深度信息。
  • WORLD——X、Y、Z坐标值定义在世界坐标系统。
  • USERDEFINED——用户自定义坐标系统。

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

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

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

vtkSmartPointer<vtkCoordinate>coordinate =
vtkSmartPointer<vtkCoordinate>::New);
coordinate->SetCoordinateSystemToNormalizedDisplay();
coordinate->SetValue(.5,.5,0);int*val;
val =coordinate_>GetComputedDisplay Value(renderer);

  这里先调用了SetCoordinateSystemToNormalizedDisplay()设置坐标系统为归一化窗口坐标,并设置坐标值为(0.5,0.5,0),即屏幕的中心;然后通过函数 GetComputedDisplayValue()实现窗口坐标的转换。该类中坐标系统转换函数如下:

GetComputedWorldValue)
GetComputedViewportValue()
GetComputedDisplayValue)
GetComputedLocalDisplayValue()
GetComputedDoubleViewportValue()
GetComputedDoubleDisplayValue)
GetComputedUserDefinedValue()

2、空间变换

  在三维空间里定义的三维模型,最后显示时都是投影到二维平面,比如在屏幕上显示。三维到二维的投影包括透视投影(Perspective Projection)和正交投影(Orthogonal Projection)。正交投影也叫平行投影。
在这里插入图片描述
在这里插入图片描述
  VTK 里与空间变换相关的类有 vtkTransform2D,vtkTransform,vtkPerspectiveTransform,vtkGeneralTransform,vtkTransformFilter,vtkMatrix4 X 4 等。例如下面代码实现了vtkActor对象的空间变换:

vtkSmartPointer<vtkTransform>transform =
vtkSmartPointer<vtkTransform>::New);
transform->PostMultiply0;
transform->RotateZ(40);
transform->Translate(10,0,0);
cylinderActor->SetUserTransform(transform);

  先定义了vtkTransform 对象,并设置使用右乘计算变换矩阵。RotateZ()设置绕 Z 轴旋转40°,并使用Translate()设置平移大小为(10,0,0),最后通过 vtkActor::SetUserTransform()方法设置用户定义的变换矩阵,实现模型的空间变换。

3、矩阵

3.1、齐次坐标

  常见的点一般是Pt(X,Y,Z),相当于一个1×3矩阵,而矩阵相乘的话一般是第一个矩阵的列数要等于第二个矩阵的行数。此处需要引入齐次坐标的概念:从广义上讲,齐次坐标就是用n+1维向量表示n 维向量,即将n维空间的点用 n+1维坐标表示。例如,一般笛卡尔坐标系中的二维点向量[x y]可用齐次坐标表示为[Hx Hx H],其中最后一维坐标是一个标量,称为比例因子。利用齐次坐标可以将平移、旋转、比例、投影等几何变换统一到矩阵的乘法上来,为图形变换提供方便。

  该矩阵在右手坐标系中定义,其中左上角部分产生比例、对称、错切和旋转变换,右上角部分产生平移变换;左下角部分产生透视变换;右下角部分产生全比例变换。
在这里插入图片描述

3.2、矩阵旋转

在这里插入图片描述
有兴趣可以将上述三个旋转矩阵按照不同的顺序进行相乘,得到的结果也是不一样的,例如:
1)先旋转x轴再旋转y轴再旋转z轴;
2)先旋转y轴再旋转x轴再旋转z轴;
3)先旋转z轴再旋转y轴再旋转x轴;

3.3、vtkMatrix4x4类

3.3.1 vtkMatrix4x4初始化
matrix1:
-0.013 -0.986 0.165 -133
-0.017 0.166 0.986 -35
-1 0.01 -0.02 40
0 0 0 1
	vtkMatrix4x4* matrix1 = vtkMatrix4x4::New();matrix1->Identity();matrix1->SetElement(0, 0, -0.013);matrix1->SetElement(0, 1, -0.986);matrix1->SetElement(0, 2, 0.165);matrix1->SetElement(0, 3, -133);matrix1->SetElement(1, 0, -0.017);matrix1->SetElement(1, 1, 0.166);matrix1->SetElement(1, 2, 0.986);matrix1->SetElement(1, 3, -35);matrix1->SetElement(2, 0, -1.0);matrix1->SetElement(2, 1, 0.01);matrix1->SetElement(2, 2, -0.02);matrix1->SetElement(2, 3, 40);
3.3.2 vtkMatrix4x4相乘

  下面两个矩阵的结果是不一样的,也就是常说的矩阵乘法左乘和右乘不一样。

	vtkMatrix4x4::Multiply4x4(matrix1, matrix2, matrix3);vtkMatrix4x4::Multiply4x4(matrix2, matrix1, matrix4);

  下面是完整的结果和代码:

在这里插入图片描述

#include <iostream>
#include <vtkMatrix4x4.h>int main()
{vtkMatrix4x4* matrix1 = vtkMatrix4x4::New();matrix1->Identity();matrix1->SetElement(0, 0, -0.013);matrix1->SetElement(0, 1, -0.986);matrix1->SetElement(0, 2, 0.165);matrix1->SetElement(0, 3, -133);matrix1->SetElement(1, 0, -0.017);matrix1->SetElement(1, 1, 0.166);matrix1->SetElement(1, 2, 0.986);matrix1->SetElement(1, 3, -35);matrix1->SetElement(2, 0, -1.0);matrix1->SetElement(2, 1, 0.01);matrix1->SetElement(2, 2, -0.02);matrix1->SetElement(2, 3, 40);vtkMatrix4x4* matrix2 = vtkMatrix4x4::New();matrix2->Identity();matrix2->SetElement(0, 3, -140);matrix2->SetElement(1, 3, -140);matrix2->SetElement(2, 3, -143);vtkMatrix4x4* matrix3 = vtkMatrix4x4::New();matrix3->Identity();vtkMatrix4x4* matrix4 = vtkMatrix4x4::New();matrix4->Identity();vtkMatrix4x4::Multiply4x4(matrix1, matrix2, matrix3);vtkMatrix4x4::Multiply4x4(matrix2, matrix1, matrix4);// 打印结果矩阵以验证std::cout << "matrix1: " << std::endl;for (int i = 0; i < 4; ++i){for (int j = 0; j < 4; ++j){std::cout << matrix1->GetElement(i, j) << " ";}std::cout << std::endl;}std::cout << "matrix2: " << std::endl;for (int i = 0; i < 4; ++i){for (int j = 0; j < 4; ++j){std::cout << matrix2->GetElement(i, j) << " ";}std::cout << std::endl;}std::cout << std::endl;std::cout << "matrix1 * matrix2: " << std::endl;for (int i = 0; i < 4; ++i) {for (int j = 0; j < 4; ++j) {std::cout << matrix3->GetElement(i, j) << " ";}std::cout << std::endl;}std::cout << std::endl;std::cout << "matrix2 * matrix1: " << std::endl;for (int i = 0; i < 4; ++i){for (int j = 0; j < 4; ++j){std::cout << matrix4->GetElement(i, j) << " ";}std::cout << std::endl;}// 释放内存matrix1->Delete();matrix2->Delete();matrix3->Delete();matrix4->Delete();return 1;
}

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

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

相关文章

java计算机毕设课设—进销存管理系统(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; 资源获取方式再最下方 java计算机毕设课设—进销存管理系统(附源码、文章、相关截图、部署视频) 一、项目简介 项目名称&#xff1a; 基于Java的进销存管理系统 开发背景&#xff1a; 在现代企业管理中&#xff0c;库存管理是核心环节之一&#…

环形链表 (简单易懂)

给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;…

RK3568笔记0:环境搭建

第1章 安装NFS服务器 NFS可以让不同的机器、不同的操作系统之间彼此共享文件 服务器安装NFS sudo apt-get install nfs-kernel-server服务器创建一个共享目录 sudo mkdir -p /home/lmz/workspaces/shared_directory配置共享目录到服务器中的配置文件中 sudo vim /etc/export…

第七届传智杯(小红的四子棋)

Q5&#xff1a;小红的四子棋 第五题大意&#xff1a;五子棋的简略版四子棋&#xff0c;给定一个棋盘&#xff0c;判断是否有棋子连成4个及以上 思路&#xff1a;模拟/穷举所有的可能&#xff08;行&#xff0c;列&#xff0c;主副对角线&#xff09; 注意所谓主对角线和副对角…

flask创建templates目录存放html文件

首先&#xff0c;创建flask项目&#xff0c;在pycharm中File --> New Project&#xff0c;选择Flask项目。 然后&#xff0c;在某一目录下&#xff0c;新建名为templates的文件夹&#xff0c;这时会是一个普通的文件夹。 然后右击templates文件夹&#xff0c;选择Unmark as …

【pyspark学习从入门到精通24】机器学习库_7

目录 聚类 在出生数据集中寻找簇 主题挖掘 回归 聚类 聚类是机器学习中另一个重要的部分&#xff1a;在现实世界中&#xff0c;我们并不总是有目标特征的奢侈条件&#xff0c;因此我们需要回归到无监督学习的范式&#xff0c;在那里我们尝试在数据中发现模式。 在出生数据…

Metasploit使用

最近在学Metasploit&#xff0c;Metasploit是一个免费的、可下载的渗透测试框架&#xff0c;通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击&#xff0c;是一个集成了渗透测试全流程的渗透工具。 图一 模块&#xff1a;模块组织按照不同的用途分为7种类型的模块 &am…

ACM:均分纸牌

主要思路 整体思路概述&#xff1a; 本题旨在解决给定N堆纸牌&#xff08;纸牌总数是N的倍数&#xff09;&#xff0c;通过按照特定移牌规则移动纸牌&#xff0c;找出用最少移动次数使每堆纸牌数量相等的方法。程序采用了一种逐步调整的思路&#xff0c;先计算出每堆纸牌应有的…

3D 生成重建020-Gaussian Grouping在场景中分割并编辑一切

3D 生成重建020-Gaussian Grouping在场景中分割并编辑一切 文章目录 0 论文工作1 方法2 实验结果 0 论文工作 最近提出的高斯Splatting方法实现了高质量的实时三维场景新视角合成。然而&#xff0c;它仅仅关注外观和几何建模&#xff0c;缺乏细粒度的物体级场景理解。为了解决…

Milvus向量数据库03-搜索理论

Milvus向量数据库03-搜索理论 1-ANN搜索 通过 k-最近邻&#xff08;kNN&#xff09;搜索可以找到一个查询向量的 k 个最近向量。kNN 算法将查询向量与向量空间中的每个向量进行比较&#xff0c;直到出现 k 个完全匹配的结果。尽管 kNN 搜索可以确保准确性&#xff0c;但十分耗…

Error relaunching VirtualBox VM process: 5 启动虚拟机时发生了错误

出现错误 一大早起来发现虚拟机打不开&#xff0c;看了虚拟机日志是正常的&#xff0c;还回了个档都不行。 最后我突然想起之前在哪看到过&#xff1a;“完美游戏平台会导致虚拟机的问题。” 解决方法 于是我把完美游戏卸载了&#xff0c;发现&#xff0c;真的&#xf…

基于Springboot的校园交友网站设计与实现

1.1 管理信息系统概述 管理信息系统是计算机在信息管理领域的一种实用技术。通过运用管理科学、数学和计算机应用的原理及方法&#xff0c;在符合软件工程规范的原则下&#xff0c;形成一套完整的理论和方法体系。是一个以人、计算机和其他外部设备组成的可以进行信息的收集、…

FinalShell找不到窗口问题

原因可能Java程序可能记住了之前的窗口位置 笔记本外接了4K显示器,但是在打开一个用Java写的桌面应用FinalShell时候,经常找不到窗口 1. winTab键,选中FinalShell 也可以直接点一下 聚焦 2.按AltSpace(空格) 放大之后 拖下就好了

重生之我在异世界学编程之C语言:深入结构体篇(下)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言结构体的自引用实现链表一、链表的基…

linux学习day03_linux文件与目录管理

1、相对路径和绝对路径的区别 绝对路径&#xff1a;路径的写法“一定由根目录 / 写起”&#xff0c;例如&#xff1a; /usr/share/doc 这个目录。 相对路径&#xff1a;路径的写法“不是由 / 写起”&#xff0c;例如由 /usr/share/doc 要到 /usr/share/man 下面 时&#xff0…

深入浅出:Gin框架中的测试与Mock

深入浅出&#xff1a;Gin框架中的测试与Mock 引言 在现代软件开发中&#xff0c;编写高质量的代码离不开有效的测试。对于Web应用程序来说&#xff0c;单元测试、集成测试和端到端测试都是确保系统稳定性和可靠性的重要手段。本文将带你深入了解如何在Gin框架中进行测试&…

未来网络技术的新征程:5G、物联网与边缘计算(10/10)

一、5G 网络&#xff1a;引领未来通信新潮流 &#xff08;一&#xff09;5G 网络的特点 高速率&#xff1a;5G 依托良好技术架构&#xff0c;提供更高的网络速度&#xff0c;峰值要求不低于 20Gb/s&#xff0c;下载速度最高达 10Gbps。相比 4G 网络&#xff0c;5G 的基站速度…

LDR6500U PD取电协议芯片:高效充电与智能管理的典范

在当今快速发展的电子设备市场中&#xff0c;高效、安全、稳定的充电技术已成为衡量设备性能的重要指标之一。而LDR6500U&#xff0c;作为乐得瑞科技有限公司针对USB PD&#xff08;Power Delivery&#xff09;协议及Quick Charge&#xff08;QC&#xff09;协议开发的一款高性…

Plugin - 插件开发05_Solon中的插件实现机制

文章目录 Pre概述插件插件扩展机制&#xff08;Spi&#xff09;插件扩展机制概述插件扩展机制的优势 插件扩展机制实现步骤第一步&#xff1a;定制插件实现类示例代码&#xff1a;插件实现类 第二步&#xff1a;通过插件配置文件声明插件示例插件配置文件&#xff1a;META-INF/…

JAVA-二叉树的概念和性质

目录 一.树形结构 1.1 概念 1.2 树的概念(重要)​编辑 补充&#xff1a;高度和深度的区别 1.3 树的应用 二. 二叉树&#xff08;重点&#xff09; 2.1 概念 2.2 两种特殊的二叉树 2.3 二叉树的性质 2.4 选择题 一.树形结构 1.1 概念 树是一种 非线性 的数据结构&…