1.拾取

选择拾取是人机交互过程的一个重要功能。
一个最经典的例子就是,在玩3D游戏时,场景中可能会存在多个角色,有时需要用鼠标来选择所要控制的角色,这就要用到拾取功能。
另外,在某些三维图形的编辑软件中,经常需要编辑其中的一个点、一个面片或者一个局部区域,这也需要通过拾取功能来完成。
VTK中定义了多个拾取功能的类,具体的继承关系如下:

VTK中所有的拾取类都继承自vtkAbstractPicker类,在这些类的基础之上可以实现非常复杂的功能。

2.点拾取

从上图中能够知晓,完成点拾取功能的类是vtkPointPicker。
vtk中的消息是通过vtkRenderWindowInteractor类处理的,在类vtkRenderWindowInteractor中,定义如下函数:
virtual void SetPicker(vtkAbstractPicker*  );
该函数用来设置具体的VTKAbstractPicker对象,并执行相应的拾取操作。因此对于点拾取,实际就是设置VTKPointPicker的过程。
之前,曾经细致的研究过,vtkRenderWindowInteractor内部定义了一个vtkInteractorStyle对象。vtkInteractorStyle类是一个虚基类,其子类定义了多种鼠标和键盘消息的处理方法,在实现拾取操作是,需要定制相应的鼠标消息处理函数。比如拾取某个点时,应该响应鼠标的左键按下消息,并在响应该消息的函数中根据鼠标的当前窗口坐标来完成拾取操作。
点拾取的示例代码如下:

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkInteractionStyle)#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>#include <vtkPointPicker.h>
//this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()
#include <vtkRendererCollection.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkObjectFactory.h>  //vtkStandardNewMacro();
#include <vtkProperty.h>#include <vtkAxesActor.h>
#include <vtkOrientationMarkerWidget.h>
/**************************************************************************************************/
class PointPickerInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:static PointPickerInteractorStyle* New();vtkTypeMacro(PointPickerInteractorStyle, vtkInteractorStyleTrackballCamera);virtual void OnLeftButtonDown(){//打印鼠标左键像素位置std::cout << "Picking pixel: " << this->Interactor->GetEventPosition()[0] << " " << this->Interactor->GetEventPosition()[1] << std::endl;//注册拾取点函数this->Interactor->GetPicker()->Pick(this->Interactor->GetEventPosition()[0],this->Interactor->GetEventPosition()[1], 0,  // always zero.this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());//打印拾取点空间位置double picked[3];this->Interactor->GetPicker()->GetPickPosition(picked);std::cout << "Picked value: " << picked[0] << " " << picked[1] << " " << picked[2] << std::endl;//对拾取点进行标记vtkSmartPointer<vtkSphereSource> sphereSource =vtkSmartPointer<vtkSphereSource>::New();sphereSource->Update();vtkSmartPointer<vtkPolyDataMapper> mapper =vtkSmartPointer<vtkPolyDataMapper>::New();mapper->SetInputConnection(sphereSource->GetOutputPort());vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();actor->SetMapper(mapper);actor->SetPosition(picked);actor->SetScale(0.05);actor->GetProperty()->SetColor(1.0, 0.0, 0.0);this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(actor);vtkInteractorStyleTrackballCamera::OnLeftButtonDown();}
};
/**************************************************************************************************/vtkStandardNewMacro(PointPickerInteractorStyle);int main()
{vtkSmartPointer<vtkSphereSource> sphereSource =vtkSmartPointer<vtkSphereSource>::New();sphereSource->Update();vtkSmartPointer<vtkPolyDataMapper> mapper =vtkSmartPointer<vtkPolyDataMapper>::New();mapper->SetInputConnection(sphereSource->GetOutputPort());vtkSmartPointer<vtkActor> actor =vtkSmartPointer<vtkActor>::New();actor->SetMapper(mapper);vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(actor);renderer->SetBackground(1, 1, 1);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->Render();renderWindow->SetWindowName("PointPicker");renderWindow->AddRenderer(renderer);vtkSmartPointer<vtkPointPicker> pointPicker =vtkSmartPointer<vtkPointPicker>::New();vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();renderWindowInteractor->SetPicker(pointPicker);renderWindowInteractor->SetRenderWindow(renderWindow);vtkSmartPointer<PointPickerInteractorStyle> style =vtkSmartPointer<PointPickerInteractorStyle>::New();renderWindowInteractor->SetInteractorStyle(style);/vtkSmartPointer<vtkAxesActor>  Axes = vtkSmartPointer<vtkAxesActor>::New();vtkSmartPointer<vtkOrientationMarkerWidget>  widget =vtkSmartPointer<vtkOrientationMarkerWidget>::New();widget->SetInteractor(renderWindowInteractor);widget->SetOrientationMarker(Axes);widget->SetOutlineColor(1, 1, 1);widget->SetViewport(0, 0, 0.2, 0.2);widget->SetEnabled(1);widget->InteractiveOn();renderWindow->Render();renderWindowInteractor->Start();return 0;
}

实际操作细节分析:

  • vtkInteractorStyleTrackballCemera派生类设计

PointPickerInteractorStyle类从vtkInteractorStyleTrackballCemera派生,并覆盖了该类OnLeftButtonDown()函数。在该函数中,调用了vtkRenderWindowInteractor的GetEventPosition()函数输出鼠标点击的屏幕坐标。

  • 拾取函数Pick()设计

int Pick(double selectionX, double selectionY, double selectionZ, vtkRender* renderer);
该函数需要接受四个参数,前三个为(selectionX,selectionY,selectionZ),即鼠标的当前窗口坐标,其中selectionZ通常为零。最后一个是vtkRenderer对象。

  • GetPackPosition()是指世界坐标系下拾取点的坐标
  • mian()函数中设计拾取调用流程
    vtkSmartPointer<vtkPointPicker> pointPicker =vtkSmartPointer<vtkPointPicker>::New();vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetPicker(pointPicker);
    renderWindowInteractor->SetRenderWindow(renderWindow);vtkSmartPointer<PointPickerInteractorStyle> style =vtkSmartPointer<PointPickerInteractorStyle>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    实例化vtkPointPicker对象以后,调用vtkRenderWindowInteractor::SetPicker()函数将其设置到渲染窗口交互器中。PointPickerInteractorStyle类与vtkInteractorStyleImage等交互器样式使用方法一致。

VTK_Learning_交互与拾取_点拾取相关推荐

  1. VTK_Learning_交互与拾取_单位拾取

    1.单位拾取 示例代码: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL) VTK_MODULE_INIT(vtkI ...

  2. VTK修炼之道79:交互与拾取_单位拾取

    1.单位拾取 示例代码: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL) VTK_MODULE_INIT(vtkI ...

  3. VTK修炼之道78:交互与拾取_点拾取

    1.拾取 选择拾取是人机交互过程的一个重要功能. 一个最经典的例子就是,在玩3D游戏时,场景中可能会存在多个角色,有时需要用鼠标来选择所要控制的角色,这就要用到拾取功能. 另外,在某些三维图形的编辑软 ...

  4. vue3.x +Cesium Cesium 鼠标交互,鼠标点击拾取对象等(五)

    cesium地图上鼠标点击事件 1.创建屏幕控制实例 var handlClick = new Cesium.ScreenSpaceEventHandler(window.viewer.canvas) ...

  5. 交互设计精髓_设计空间的精髓

    交互设计精髓 重点 (Top highlight) 什么是空间? (What is Space?) Space is the dimension of height, depth and width ...

  6. 鼠标拾取(光线拾取)

    作者:桑榆 QQ:934440653 有问题,评论留言,或qq联系 案例效果 鼠标拾取 主要代码 1.创建矩形 (1)6-8行限制随机产生的矩形的长.宽.纵深不超过20: (2)14-16行限制随机产 ...

  7. python打开交互界面设计_老司机必备——用PyQt做一个有交互界面的妹子图爬虫...

    内容简介:老司机必备--用PyQt做一个有交互界面的妹子图爬虫 代码飙车,指日可待.今天的课程教大家结合PyQt和 Python 爬虫技术,做一个带有交互界面的妹子图网站爬虫程序. 一.实验简介 1. ...

  8. python交互界面制作_Python 如何编写交互界面?_后端开发

    c语言怎么实现三个数从小到大输出?_后端开发 方法:1.使用if语句对数字x与y进行比较,若x>y则交换x和y的值:2.使用if对x与z进行比较,若x>z则交换x和z的值:3.使用if对y ...

  9. python图表交互控件_用djang中的交互式控件制作bokeh图表

    有两个用例: 没有服务器 如果您可以在JS中执行任何更新(不需要调用实际的python代码),那么使用CustomJS callbacks添加交互非常容易.在这个链接中有很多示例,但是一个基本的简单代 ...

最新文章

  1. FPGA基础知识极简教程(8)详解三态缓冲器
  2. 解锁bios学习总结
  3. 给老婆普及计算机知识
  4. concat函数_三、P57-61 MySQL中常用函数
  5. 生成路径 vs 设置_Simulink代码生成之模型配置
  6. Tail Recursion尾递归
  7. C++工作笔记-WM_KEYFIRST和WM_KEYDOWN的用法
  8. 操作系统之内存管理:6、页面分配策略、抖动、工作集
  9. 基本值类型(一):序数类型与运算符
  10. 【LeetCode】24. Swap Nodes in Pairs
  11. NIPS不改名再引风波:签名抗议活动开启,大咖纷纷发声支持
  12. 《Python语言程序设计》——1.3 程序设计语言
  13. 普林斯顿大学计算机系,普林斯顿大学计算机科学系
  14. 论文精读:《电子政务的服务质量、感知价值与公民持续使用意愿——来自中国的实证经验》
  15. lopatkin俄大神精简中文系统Windows 7 Enterprise SP1 7601.23934 x86-x64 ZH-CN PIP
  16. Android PreferenceScreen的使用和详解(设置页面)
  17. 【车辆分类】基于matlab的视频中车辆跟踪监测分类算法仿真,包括背景差分与帧间差分以及形态学处理
  18. php 调用redis中lpush的方法
  19. 计算的威力,智慧的传奇——Fabrice Bellard
  20. c语言数组转换树存储结构,c语言, 一棵具有n个结点的完全二叉树以数组存储,试写一个非递归 算法实现对 该树的前序遍历。...

热门文章

  1. OSChina 周六乱弹 —— 广州爱情故事
  2. PyCharm配置SSH和SFTP连接远程服务器
  3. 【wsl2】从头开始配置
  4. 用户画像原理、技术选型及架构实现
  5. 当ChatGpt接入微信群之后。。。
  6. 看了后非常震撼---骗局
  7. 高并发解决方案——提升高并发量服务器性能解决思路
  8. unl文件导入orcle数据库
  9. mq5 EA模板及双均线交叉策略EAdemo
  10. gadget驱动框架(三)