首页 > 其他分享 >VTK使用交互器来从三维体数据中提取二维切片

VTK使用交互器来从三维体数据中提取二维切片

时间:2024-04-05 13:32:01浏览次数:30  
标签:vtkCommand interactor 提取 鼠标 VTK vtkImageSlice 切片 器来

VTK中鼠标消息是在交互类型对象(interactorstyle)中响应,因此通过为交互类型对象(interactorstyle)添加观察者(observer)来监听相应的消息,当消息触发时,由命令模式执行相应的回调函数

vtkImageInteractionCallback继承自vtkCommand类,并覆盖父类函数Execute()。
该类提供了两个接口:SetImageReslice和SetInteractor。
SetImageReslice用以设置vtkImageSlice对象,vtkImageSlice根据设置的变换矩阵提取三维图像切片。SetInteractor用以设置vtkRenderWindowInteractor,vtkRenderWindowInteractor类对象负责每次提取切片后刷新视图

class vtkImageInteractionCallback : public vtkCommand
{
public:
	static vtkImageInteractionCallback *New() //回调函数初始化函数
	{
		return new vtkImageInteractionCallback;
	}
	vtkImageInteractionCallback()
	{
		this->Slicing = 0;//切片提取标志位,为1时提取切片
		this->ImageReslice = 0;//vtkImageSlice对象的变换矩阵,用来确定切面在三维图像中的位置
		this->Interactor = 0;
	}
	void SetImageReslice(vtkImageReslice *reslice)
	{
		this->ImageReslice = reslice;
	}
	vtkImageReslice *GetImageReslice()
	{
		return this->ImageReslice;
	}
	void SetInteractor(vtkRenderWindowInteractor *interactor)
	{
		this->Interactor = interactor;
	}
	vtkRenderWindowInteractor *GetInteractor()
	{
		return  this->Interactor;
	}
	virtual void Execute(vtkObject * ,unsigned long event,void *)
	{
		//具体内容放下面
	}
private:
	int Slicing;
	vtkImageReslice *ImageReslice;
	vtkRenderWindowInteractor *Interactor;
};


下面重点看Execute函数,该函数提供了具体的切片提取功能。在该函数里面,主要监听了三个消息:
vtkCommand::LeftButtonPressEvent,
vtkCommand::LeftButtonReleaseEvent,
vtkCommand::MouseMoveEvent,
前两个消息分别是鼠标左键的按下和弹起消息。当鼠标左键按下时,就设置切片提取标志为1,而当弹起时,将标志置为0。这样在鼠标移动时,只有在确定切片提取标志为1时,执行切片提取功能。
vtkCommand::MouseMoveEvent即为鼠标移动消息。当检测到该消息时,首先检查切片提取标志,当为1时提取切片。提取切片时,需要为vtkImageSlice对象设置变换矩阵。这里在函数开始时,首先获取了鼠标滑动的前后两次点的位置lastPos和currPos。然后根据两点的Y坐标差deltaY,计算新的中心点center并变换至vtkImageSlice当前变换矩阵中,得到变换中心点,将其设置到原来的变换矩阵matrix中,并设置到vtkImageSlice中,最后执行interactor->Render()即可不断的根据鼠标移动刷新图像。

virtual void Execute(vtkObject * ,unsigned long event,void *)
{
        vtkRenderWindowInteractor *interactor = GetInteractor();
		int lastPos[2];
		interactor->GetLastEventPosition(lastPos);
		int currPos[2];
		interactor->GetEventPosition(currPos);
 
		if (event == vtkCommand::LeftButtonPressEvent)
		{
			this->Slicing = 1; //标志位 
		}
		else if (event == vtkCommand::LeftButtonReleaseEvent)
		{
			this->Slicing = 0; //标志位 
		}
		else if (event == vtkCommand::MouseMoveEvent)
		{
			if (this->Slicing)//检验鼠标左键已经按下 正在执行操作
			{
				vtkImageReslice *reslice = this->ImageReslice;
				//记下鼠标Y向变化的幅值大小
				int deltaY = lastPos[1] - currPos[1];
 
				reslice->Update();
				double sliceSpacing = reslice->GetOutput()->GetSpacing()[2];
				vtkMatrix4x4 *matrix = reslice->GetResliceAxes();
				//重新定位切片需要经过的中心点
				double point[4];
				double center[4];
				point[0] = 0;
				point[1] = 0;
				point[2] = sliceSpacing*deltaY;
				point[3] = 1.0;
				matrix->MultiplyPoint(point, center);
				matrix->SetElement(0, 3, center[0]);
				matrix->SetElement(1, 3, center[1]);
				matrix->SetElement(2, 3, center[2]);
 
				interactor->Render();
			}
			else
			{
				vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(
					interactor->GetInteractorStyle());
				if (style)
				{
					style->OnMouseMove();
				}
			}
		}
}

Command对象定义完毕后,即可为交互对象InteractorStyle添加观察者,响应鼠标消息。
这里主要是定义了vtkImageInteractionCallback对象,并设置vtkImageSlice对象和vtkRenderWindowInteractor对象。然后为交互对象vtkInteractorStyle添加观察者来监控相应的消息。

vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();//定义交互对象

	vtkSmartPointer<vtkInteractorStyleImage> imagestyle =
		vtkSmartPointer<vtkInteractorStyleImage>::New();//定义交互模式
 
	renderWindowInteractor->SetInteractorStyle(imagestyle);//设置交互模式
	renderWindowInteractor->SetRenderWindow(renderWindow);//连接交互器与显示窗口
	renderWindowInteractor->Initialize();//交互器初始化

	//****************建立 观察者-命令 模式****************//
	vtkSmartPointer<vtkImageInteractionCallback> callback =
		vtkSmartPointer<vtkImageInteractionCallback>::New();//设置回调函数
	callback->SetImageReslice(reslice);//为vtkImageSlice对象设置变换矩阵,确定矩阵对应的切片位置
	callback->SetInteractor(renderWindowInteractor);
 
	imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);//鼠标移动对应的回调函数
	imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);//按下鼠标左键对应的回调函数
	imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);//按下鼠标右键对应的回调函数
 
	renderWindowInteractor->Start();

这里主要是三个消息:
vtkCommand::LeftButtonPressEvent,
vtkCommand::LeftButtonReleaseEvent,
vtkCommand::MouseMoveEvent,
当响应到这三个消息时,立即执行vtkImageInteractionCallback的Execute函数,以便实现切片的实时提取和更新。完成以后,运行程序,当鼠标在图像上移动时,会发现图像会跟着鼠标的移动而变化。

标签:vtkCommand,interactor,提取,鼠标,VTK,vtkImageSlice,切片,器来
From: https://blog.csdn.net/weixin_55035144/article/details/137398531

相关文章

  • Vaadin框架是如何处理前后端交互的?列举几个Vaadin中常用的UI组件,并描述它们的作用。如
    Vaadin框架是如何处理前后端交互的?Vaadin框架处理前后端交互的方式主要基于服务端渲染和事件驱动的编程模型。以下是具体的处理过程:服务端渲染:Vaadin应用程序的UI组件是在服务器端创建和渲染的。当用户在浏览器中访问应用程序时,服务器会生成HTML和JavaScript代码,并将其发......
  • VTK的观察者-事件回调方案
    1.创建一个VTKCallbackCommand对象,并调用VTKCallbackCommand::SetCallback()函数设置所定义的回调函数。//Step1:设置事件回调函数vtkSmartPointer<vtkCallbackCommand>mouseCallback=vtkSmartPointer<vtkCallbackCommand>::New();mouseCallback->SetCallback(MyCallba......
  • 切片的使用
    前言虽然切片在实际写代码的时候经常会用到,经过调试也一般都能用对,不过真正通过脑袋想的时候,经常也会搞错,基本的使用场景应该在下面都囊括了。切片虽然是闭区间,切片时是前包后不包message="我叫齐天大圣"print(message[0:2])#我叫起始为空时,代表从第一个开始#开始值默......
  • golang—踩坑之切片
    1.记录一次切片引用错误,希望大家不要踩坑,用来惊醒自己!修改之前:import("context""encoding/json""feishu/global""feishu/structure""feishu/utils""fmt""github.com/gin-gonic/gin"......
  • 由浅到深认识Go语言(8):切片
    该文章Github地址:https://github.com/AntonyCheng/go-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直......
  • NumPy库中的ndarray对象——ndarray的切片和索引
    一、普通切片与索引ndarray对象的内容可以通过索引或切片来访问和修改,与Python中list的切片操作一样。ndarray数组可以基于0-n的下标进行索引,切片对象可以通过内置的slice函数,并设置start,stop及step参数进行,从原数组中切割出一个新数组。我们来介绍一下sta......
  • 如何实现Python中的字符串切片?
    如何实现Python中的字符串切片?在Python中,字符串切片是一种强大的功能,它允许我们访问和操作字符串中的特定部分。字符串切片的基本语法是[start:stop:step],其中start是切片的起始索引,stop是切片的结束索引(但不包括该索引处的字符),step是切片时每次跳过的字符数。如果省略某个参......
  • Go 切片
    Go切片切片结构源码包src/runtime/slice.go中定义slice的结构为typeslicestruct{arrayunsafe.Pointerlenintcapint}array指针指向底层数组len表示切片长度cap表示切片容量切片扩容机制go1.18之后:growslice方法中可以得知go切片......
  • 【VTKExamples::Points】第十期 NormalEstimation
    很高兴在雪易的CSDN遇见你 VTK技术爱好者QQ:870202403   公众号:VTK忠粉前言本文分享VTK样例NormalEstimation,并解析接口vtkPCANormalEstimation,希望对各位小伙伴有所帮助!感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!你的点赞就是我的动力(^U^)ノ~YO1.Norm......
  • c语言 实现切片数组
    c语言集合类第一章切片(本章)第二章栈文章目录c语言集合类前言一、接口定义1、创建切片2、销毁切片3、添加元素4、切片长度5、切片容量二、完整代码三、使用示例1、一般使用流程2、直接append3、自定义类型总结前言由于c语言没有集合类的标准库,需要用时只能自......