VTK中oberver 和 command 的信息机制详解

前言

看了东灵出版的书的第八章,有点迷糊,这里简单做些笔记。


正文

观察者/命令模式(Observer / Command)

目的: 实现VTK的交互功能

定义: 一个vtkObject (包括它的子类) 可以拥有多个 Observer。  就是观察者在对象的状态发生改变时,调用相应的函数或者说是执行预定的动作。


实现

  • 事件回调函数
示例
//第一步,定义回调函数。注意回调函数的签名,不能更改。
void CallbackFunc(vtkObject*, unsigned long eid, void* clientdata, void *calldata)
{
     std::cout<<" ZYH "<<std::endl;
}
//第二步,将回调函数和 vtkCallbackCommand 联系起来
vtkSmartPointer<vtkCallbackCommand> mouseCallback = vtkSmartPointer<vtkCallbackCommand>::New();
mouseCallback->SetCallback ( CallbackFunc );

//第三步,将vtkCallbackCommand对象添加到观察者列表。
interactor->AddObserver(vtkCommand::LeftButtonPressEvent, mouseCallback);

步骤就是上面所示的三步,需要注意的是:

① 灰调函数除了函数名可以自己重新定义,其他的是固定格式的

void func(vtkObject *obj, unsigned long eid, void *clientdata, void *calldata)

 

② AddObserver函数是将事件、回调函数、VTK对象联系在一起


  • 从vtkCommand派生出具体的子类
command的子类,绑定到vtk对应的事件中,即可实现观察者模式的消息响应机制 

示例  (种子点)
步骤一:
派生子类, 实现vtkCommand::Execute()
class vtkSeedCallback : public vtkCommand
{
public:
	static vtkSeedCallback *New()
	{ 
		return new vtkSeedCallback; 
	}

	vtkSeedCallback() {}
        //继承函数,实现回调时的响应操作,第一个参数是调用该事件的对象,第二个参数树消息类型,第三个参数为可以传递给 command 的参数  
	virtual void Execute(vtkObject*, unsigned long event, void *calldata)
	{
		if (event == vtkCommand::PlacePointEvent)
		{
			std::cout << "Placing point..." << std::endl;
			std::cout << "There are now " << this->SeedRepresentation->GetNumberOfSeeds() << " seeds." << std::endl;
			for(unsigned int seedId = 0; seedId < this->SeedRepresentation->GetNumberOfSeeds(); seedId++)
			{
				double pos[3];
				this->SeedRepresentation->GetSeedDisplayPosition(seedId, pos);
				std::cout << "Seed " << seedId << " : (" << pos[0] << " " << pos[1] << " " << pos[2] << ")" << std::endl;
			}
			return;
		}
		if (event == vtkCommand::InteractionEvent)
		{
			std::cout << "Interaction..." << std::endl;
			if (calldata)
			{
				double pos[3];
				this->SeedRepresentation->GetSeedDisplayPosition(0, pos);
				std::cout << "Moved to (" << pos[0] << " " << pos[1] << " " << pos[2] << ")" << std::endl;
			}
			return;
		}
	}

	void SetRepresentation(vtkSmartPointer<vtkSeedRepresentation> rep)
	{
		this->SeedRepresentation = rep;
	}
	void SetWidget(vtkSmartPointer<vtkSeedWidget> widget) 
	{
		this->SeedWidget = widget;
	}

private:
	vtkSeedRepresentation* SeedRepresentation;
	vtkSeedWidget* SeedWidget;
};

实现种子点的交互【个人觉得这个InteractorEvent这个有点麻烦,只要focus到这个窗口也响应,移动种子点也响应
需要注意的是种子点的坐标是窗口坐标。
程序需要实现的功能一般都在 Execute() 函数中。

步骤二:
在主程序中实例化一个子类对象以及调用相关的方法
	// Create the representation  设置点的颜色
	vtkSmartPointer<vtkPointHandleRepresentation2D> handle = vtkSmartPointer<vtkPointHandleRepresentation2D>::New();
	handle->GetProperty()->SetColor(1,0,0);
	vtkSmartPointer<vtkSeedRepresentation> rep = vtkSmartPointer<vtkSeedRepresentation>::New();
	rep->SetHandleRepresentation(handle);

	// Seed widget
	vtkSmartPointer<vtkSeedWidget> seedWidget = vtkSmartPointer<vtkSeedWidget>::New();
	seedWidget->SetInteractor(renderWindowInteractor);
	seedWidget->SetRepresentation(rep);

	<strong>vtkSmartPointer<vtkSeedCallback> seedCallback = vtkSmartPointer<vtkSeedCallback>::New();</strong>
	seedCallback->SetRepresentation(rep);
	seedCallback->SetWidget(seedWidget);
	seedWidget->AddObserver(vtkCommand::PlacePointEvent,seedCallback);
	seedWidget->AddObserver(vtkCommand::InteractionEvent,seedCallback);

	renderWindow->Render();
	renderWindowInteractor->Initialize();
	renderWindow->Render();
	seedWidget->On();

AddObserver 监听感兴趣的事件

这个示例是VTK官网上的示例,参见


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 首先需要安装vtk库,可以使用pip命令进行安装:`pip install vtk` 2. 在代码导入vtk库:`import vtk` 3. 创建vtk数据对象,例如vtkStructuredGrid:`grid = vtk.vtkStructuredGrid()` 4. 设置vtk数据对象的大小和属性,例如设置vtkStructuredGrid的尺寸:`grid.SetDimensions(nx, ny, nz)` 5. 将流场数据保存到vtk数据对象,例如将速度场保存到vtkStructuredGrid:`grid.GetPointData().SetVectors(vx, vy, vz)` 6. 创建vtk数据写入器,例如vtkStructuredGridWriter:`writer = vtk.vtkStructuredGridWriter()` 7. 将vtk数据对象和文件名设置给vtk数据写入器:`writer.SetInputData(grid)`和`writer.SetFileName(filename)` 8. 执行vtk数据写入器的写入操作:`writer.Write()` 完整代码示例: ```python import vtk # 创建vtkStructuredGrid nx, ny, nz = 10, 10, 10 grid = vtk.vtkStructuredGrid() grid.SetDimensions(nx, ny, nz) # 设置vtkStructuredGrid的点坐标 x = vtk.vtkFloatArray() x.SetName("x") y = vtk.vtkFloatArray() y.SetName("y") z = vtk.vtkFloatArray() z.SetName("z") for i in range(nx): for j in range(ny): for k in range(nz): x.InsertNextValue(i) y.InsertNextValue(j) z.InsertNextValue(k) grid.SetPoints(vtk.vtkPoints()) grid.GetPoints().SetData(x, y, z) # 设置vtkStructuredGrid的速度场 vx = vtk.vtkFloatArray() vx.SetName("vx") vy = vtk.vtkFloatArray() vy.SetName("vy") vz = vtk.vtkFloatArray() vz.SetName("vz") for i in range(nx*ny*nz): vx.InsertNextValue(1.0) vy.InsertNextValue(0.0) vz.InsertNextValue(0.0) grid.GetPointData().SetVectors(vx, vy, vz) # 创建vtkStructuredGridWriter filename = "flow.vtk" writer = vtk.vtkStructuredGridWriter() writer.SetInputData(grid) writer.SetFileName(filename) # 执行写入操作 writer.Write() ``` 这样就可以将流场信息保存到vtk文件了。可以使用ParaView等工具打开vtk文件进行可视化和分析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值