可通过小球进行旋转的十字光标(vtkResliceCursor)
前一段事件看到VTK的一个例子:
该案例是vtk.js写的,觉得很有意思,个人正好也要用到,于是萌生了用C++修改VTK源码来实现该功能的想法。原本以为很简单,只需要修改一下vtkResliceCursor就可以了,加上小球,加上几个Actor,就能实现,没想到该功能整花了我差不多一个月的时间。但也学到了不少知识,下面就该功能的实现效果和方法做个大致解说:
我实现的效果:
实现方法:
1,首先在vtkResliceCursor中定义六个小球的位置。因为是X,Y,Z三个轴,每个轴上两个小球,所以总共有六个小球。代码:
void vtkResliceCursor::BuildCursorGeometryWithoutHole()
{// 其他源码省略.......for (int i = 0; i < 3; i++){//wulc{this->SpherePoints[0][i] = this->Center[i] - sphereLength * this->XAxis[i];this->SpherePoints[1][i] = this->Center[i] + sphereLength * this->XAxis[i];this->SpherePoints[2][i] = this->Center[i] - sphereLength * this->YAxis[i];this->SpherePoints[3][i] = this->Center[i] + sphereLength * this->YAxis[i];this->SpherePoints[4][i] = this->Center[i] - sphereLength * this->ZAxis[i];this->SpherePoints[5][i] = this->Center[i] + sphereLength * this->ZAxis[i];}}// 其他源码省略.......
}sphereLength 是一个自定义的常数,也就是中心到小球的距离。可以是 30 ,40 ,50 .。。。。
除此之外我们还要定义一个函数,通过该函数可以获取这六个小球的坐标。比如 GetPointPosition(double p[6][3]);
2,在vtkResliceCursorPicker中判断鼠标是否靠近小球中心位置,靠近小球坐标时,将鼠标光标变为手掌形状。判断方法就是鼠标的位置和小球位置的距离,其中有现成的代码:
/----------------wulc---------------------------------------------------
int vtkResliceCursorPicker::IntersectPointWithPoint(double p1[3], double p2[3], double Points[], double tol)
{double pts[6][3] = { {0,0,0} };for (size_t i = 0; i < 6; i++){pts[i][0] = Points[3*i];pts[i][1] = Points[3*i + 1];pts[i][2] = Points[3 * i + 2];}int j = 0;for ( ; j < 6; j++){double X[4] = { pts[j][0], pts[j][1], pts[j][2], 1 };int i;double ray[3], rayFactor, projXYZ[3];for (i = 0; i < 3; i++){ray[i] = p2[i] - p1[i];}if ((rayFactor = vtkMath::Dot(ray, ray)) == 0.0){return 0;}const double t = (ray[0] * (X[0] - p1[0]) +ray[1] * (X[1] - p1[1]) +ray[2] * (X[2] - p1[2])) / rayFactor;if (t >= 0.0 && t <= 1.0){for (i = 0; i < 3; i++){projXYZ[i] = p1[i] + t * ray[i];if (fabs(X[i] - projXYZ[i]) > tol){break;}}if (i > 2) // within tolerance{return 1;}}}return 0;
}
3,最后要在vtkResliceCursorActor类中添加小球,代码:
//wulcif (this->Renderer == nullptr) return;if (axisNormal == 1)//x-z平面{double* position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(2);if (fabs(position[0] - 0.0) > 0.001 || fabs(position[1] - 0.0) > 0.001 || fabs(position[2] - 0.0) > 0.001){this->SphereActor[2]->GetProperty()->SetColor(1, 0, 0);this->SphereActor[3]->GetProperty()->SetColor(1, 0, 0);this->SphereActor[2]->SetPosition(position[0], position[1], position[2]);this->SphereActor[3]->SetPosition(position[3], position[4], position[5]);position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(0);this->SphereActor[0]->GetProperty()->SetColor(0, 0, 1);this->SphereActor[1]->GetProperty()->SetColor(0, 0, 1);this->SphereActor[0]->SetPosition(position[0], position[1], position[2]);this->SphereActor[1]->SetPosition(position[3], position[4], position[5]);}}else if (axisNormal == 2)//x-y平面{double* position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(0);if (fabs(position[0] - 0.0) > 0.001 || fabs(position[1] - 0.0) > 0.001 || fabs(position[2] - 0.0) > 0.001){this->SphereActor[0]->GetProperty()->SetColor(0, 1, 0);this->SphereActor[1]->GetProperty()->SetColor(0, 1, 0);this->SphereActor[0]->SetPosition(position[0], position[1], position[2]);this->SphereActor[1]->SetPosition(position[3], position[4], position[5]);position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(1);this->SphereActor[2]->GetProperty()->SetColor(1, 0, 0);this->SphereActor[3]->GetProperty()->SetColor(1, 0, 0);this->SphereActor[2]->SetPosition(position[0], position[1], position[2]);this->SphereActor[3]->SetPosition(position[3], position[4], position[5]);}}else if (axisNormal == 0) //y-z平面{double* position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(2);if (fabs(position[0] - 0.0) > 0.001 || fabs(position[1] - 0.0) > 0.001 || fabs(position[2] - 0.0) > 0.001){this->SphereActor[0]->GetProperty()->SetColor(0, 1, 0);this->SphereActor[1]->GetProperty()->SetColor(0, 1, 0);this->SphereActor[0]->SetPosition(position[0], position[1], position[2]);this->SphereActor[1]->SetPosition(position[3], position[4], position[5]);position = this->CursorAlgorithm->GetResliceCursor()->GetSpherePostion(1);this->SphereActor[2]->GetProperty()->SetColor(0, 0, 1);this->SphereActor[3]->GetProperty()->SetColor(0, 0, 1);this->SphereActor[2]->SetPosition(position[0], position[1], position[2]);this->SphereActor[3]->SetPosition(position[3], position[4], position[5]);}}
这就可以了,欢迎小伙伴能够一块讨论。
相关文章:

可通过小球进行旋转的十字光标(vtkResliceCursor)
前一段事件看到VTK的一个例子: 该案例是vtk.js写的,觉得很有意思,个人正好也要用到,于是萌生了用C修改VTK源码来实现该功能的想法。原本以为很简单,只需要修改一下vtkResliceCursor就可以了,加上小球&#…...
python遍历文件夹并计算某类文件的数量,制图像文件到目标文件夹
python遍历文件夹并计算某类文件的数量,制图像文件到目标文件夹 在Python中,你可以使用os和os.path模块来遍历文件夹(目录)。下面是一个简单的示例,展示了如何遍历一个文件夹中的所有文件和子文件夹: imp…...

网络层只懂路由?这9个知识点被严重低估了
号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部 下午好,我的网工朋友。 网络层想必你已经耳熟能详,它的作用自然是不容小觑。 它负责将数据从源头准确地投递到目的地&am…...
最新的kali Linux源,解决apt update报错说没有数字签名
原因: 国内源的地址大部分都是http开头,这些地址早就无法使用。 解决方案: wget archive.kali.org/archive-key.asc //下载签名 apt-key add archive-key.asc //安装签名 另外,需…...

RAG与Langchain简介
RAG与Langchain简介 什么是RAGRAG解决的问题RAG工作流程RAG调优策略LangChain简介 什么是RAG 检索增强生成(Retrieval-Augmented Generation),主要是通过从外部给大模型补充一些知识,相当于给模型外挂了一个知识库,让…...

绕过网页的阻止复制
绕过网页的阻止复制 一、问题的提出二、绕过技巧一三、绕过技巧二四、绕过技巧三五、总结说明 一、问题的提出 也是很久没有写文章了,今天突发奇想写一篇文章。首先你有没有被网页中的一些阻止你复制的页面所困扰。就是那种,你突然找到一篇文章…...
Jackson指定json的key
指定json的key 要在序列化JavaBean时指定JSON的key,可以使用JsonProperty注解来指定JavaBean属性序列化到JSON时使用的key。以下是一个简单的示例: import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.da…...

谷歌发布Infini-Transformer模型—无限注意力机制长度,超越极限
Transformer 是一种基于自注意力机制的深度学习模型,最初应用于自然语言处理领域,现已扩展到图像、音频等多个领域。与传统的循环神经网络 (RNN) 不同,Transformer 不依赖于顺序数据处理,能够并行计算,从而显著提高效率…...

激光点云配准算法——Cofinet / GeoTransforme / MAC
激光点云配准算法——Cofinet / GeoTransformer / MAC GeoTransformer MAC是当前最SOTA的点云匹配算法,在之前我用总结过视觉特征匹配的相关算法 视觉SLAM总结——SuperPoint / SuperGlue 本篇博客对Cofinet、GeoTransformer、MAC三篇论文进行简单总结 1. Cofine…...
socket--cs--nc简单实现反弹shell
socket_client.py import socket#客户端: #连接服务段的地址和端口 #输入命令发送执行 #回显命令执行结果# ipinput(please input connect ip:) # portinput(please input connect port:)ssocket.socket() # IP and PORT s.connect((,9999)) while True:cmdlineinput(please i…...

CSS入门基础2
目录 1.标签类型 2.块元素 3.行内元素 4.行内块元素 5.标签行内转换 6.背景样式 1.标签类型 标签以什么方式进行显示,比如div 自己占一行, 比如span 一行可以放很多个HTML标签一般分为块标签和行内标签两种类型: 块元素行内元素。 2.块…...

Mac vscode could not import github.com/gin-gonic/gin
问题背景: 第一次导入一个go的项目就报红 问题分析: 其实就是之前没有下载和导入gin这个web框架包 gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确。 问题解决: 依次输入以下命令。通…...

MySQL修改用户权限(宝塔)
在我们安装好的MySQL中,很可能对应某些操作时,不具备操作的权限,如下是解决这些问题的方法 我以宝塔创建数据库为例,创建完成后,以创建的用户名和密码登录 这里宝塔中容易发生问题的地方,登录不上去&#…...
论文阅读(一种新的稀疏PCA求解方式)Sparse PCA: A Geometric Approach
这是一篇来自JMLR的论文,论文主要关注稀疏主成分分析(Sparse PCA)的问题,提出了一种新颖的几何解法(GeoSPCA)。 该方法相比传统稀疏PCA的解法的优点:1)更容易找到全局最优ÿ…...

Chrome/Edge浏览器视频画中画可拉动进度条插件
目录 前言 一、Separate Window 忽略插件安装,直接使用 注意事项 插件缺点 1 .无置顶功能 2.保留原网页,但会刷新原网页 3.窗口不够美观 二、弹幕画中画播放器 三、失败的尝试 三、Potplayer播放器 总结 前言 平时看一些视频的时候ÿ…...
pg修炼之道学习笔记
一、数据库逻辑结构介绍 1、一个pg数据库服务下有多个db(多个数据库),当应用连接到一个数据库时,一般只能访问这个数据库中的数据,而不能访问其他数据库的内容(限制) 2、表索引:一…...

使用宝塔面板部署Django应用(不成功Kill Me!)
使用宝塔面板部署Django应用 文章目录 使用宝塔面板部署Django应用 本地操作宝塔面板部署可能部署失败的情况 本地操作 备份数据库 # 备份数据库 mysqldump -u root -p blog > blog.sql创建requirements # 创建requirements.txt pip freeze > requirements.txt将本项目…...
c++深拷贝、浅拷贝
在 C 中,深拷贝和浅拷贝是两个重要的概念,尤其在涉及动态内存分配和指针成员时。这两个概念描述了对象复制时的行为。 浅拷贝 浅拷贝是指复制对象时,仅复制对象的基本数据成员,对于指针成员,只复制指针地址ÿ…...
k8s核心组件
Master组件: kube-apiserver:用于暴露Kubernetes API,任何资源请求或调用操作都是通过kube-apiserver提供的接口进行。它是Kubernetes集群架构的大脑,负责接收所有请求,并根据用户的具体请求通知其他组件工作。etcd&am…...

反编译腾讯vmp
反编译腾讯vmp 继续学习的过程 多翻译几个vmp 学习 看看他们的是怎么编译的 写一个自己的vmp function __TENCENT_CHAOS_VM(U, T, g, D, j, E, K, w) {// U指令起点// T是指令list// g是函数this 或window对象// D是内部变量和栈}for (0; ;)try {for (var B !1; !B;) {let no…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...