可通过小球进行旋转的十字光标(vtkResliceCursor)

news/2024/6/26 21:56:55

        前一段事件看到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类中添加小球,代码:

//wulc
  if (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]);
	   
	  }

  }

这就可以了,欢迎小伙伴能够一块讨论。


http://lihuaxi.xjx100.cn/news/2218454.html

相关文章

【机器学习300问】120、该怎么用RNN来构建语言模型?

一、基本概念补充 在构建语言模型之前补充几个自然语言处理&#xff08;NLP&#xff09;基本概念。 &#xff08;1&#xff09;语料库&#xff08;Corpus&#xff09; ① 语料库的定义 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;语料库是一个经过组织和加工…

深入理解Java中的事件驱动架构与CQRS模式

引言 在现代软件架构中&#xff0c;事件驱动架构&#xff08;Event-Driven Architecture, EDA&#xff09;和CQRS&#xff08;Command Query Responsibility Segregation&#xff09;模式因其能够提供高度的可扩展性和灵活性而变得越来越流行。本文将深入探讨这两种模式的概念…

低代码、无代码的区别在哪?

低代码和无代码有什么不一样&#xff1f;相信很多人会对这两个概念产生混淆。 顾名思义&#xff0c;低代码开发平台只是减少了编写代码的数量&#xff0c;并不是完全不需要编写代码。 而无代码开发平台是完全不需要编写任何代码&#xff0c;只需要拖拽平台上的功能组件就能够…

nginx安装环境部署(完整步骤)

在部署nginx前&#xff0c;我们需要进行环境的部署 1.编译工具gcc&#xff0c;g,autoconf&#xff0c;automake &#xff0c;make sudo apt-get install gcc g autoconf automake make 2.依赖库zlib&#xff0c;openssl&#xff0c;pcre 2.1 openssl下载地址 https://www.open…

别再这么起号了!TikTok小白起号误区,你中招了吗?

看过不少Tiktok新手的起号失败案例&#xff0c;总结下来就是以下这几个问题&#xff0c;今天结合一些个人起号心得给大家分享怎么成功在TK起号&#xff0c;希望对大家有所帮助。 手机/网络环境 首先我们要确保手机环境和网络环境没有问题&#xff0c;如果被TK判断出是非海外用户…

《软件定义安全》之八:软件定义安全案例

第8章 软件定义安全案例 1.国外案例 1.1 Fortinet&#xff1a;传统安全公司的软件定义方案 Fortinet的软件定义安全架构强调与数据中心的结合&#xff0c;旨在将安全转型为软件定义的模式&#xff0c;使安全运维能够与数据中心的其他部分一样灵活、弹性。在Fortinet看来&…

在ubuntu中创建容器并挂载windows共享的文件

Ubuntu关闭防火墙的方法如下&#xff1a; 打开终端&#xff0c;输入 sudo ufw status 回车&#xff0c;查看防火墙状态&#xff0c;inactive是关闭&#xff0c;active是开启。使用 sudo ufw enable 开启防火墙。使用 sudo ufw disable 关闭防火墙。打开“系统设置”&#xff…

Openwifi开源项目的结构

目录 1.前言2.已经有了Openwifi&#xff0c;为什么我还要再去写这部分3.Openwifi的文件构架 微信公众号获取更多FPGA相关源码&#xff1a; 1.前言 Openwifi 是一个关于wifi 系统的开源项目&#xff0c;兼容全栈 IEEE802.11/Wi-Fi 设计&#xff0c;基于 SDR&#xff08;软件定…