三维控件中定位一个点_vtkPointWidget


开发环境:

  1. Windows 11 家庭中文版
  2. Microsoft Visual Studio Community 2019
  3. VTK-9.3.0.rc0
  4. vtk-example
  5. 参考代码

demo解决问题:允许用户使用三维光标在三维空间中定位一个点。关键类vtkPointWidget , 光标具有轮廓边界框、轴对齐十字准线和轴阴影(轮廓和阴影可以关闭)。(可以关闭轮廓和阴影)。vtkPointWidget 和其他 3D widget 一样,具有一个很好的特点,即它可以与当前的交互样式一起工作。也就是说,如果 vtkPointWidget 没有处理事件,那么所有其他已注册的观察者(包括交互样式)都有机会处理该事件。否则,vtkPointWidget 将终止处理它所处理的事件。

在这里插入图片描述

主流程:(不看probe)

  1. 数据源1:构造一个网格化的sphereSource数据源
  2. 数据源2:point的位置使用cone符号化为圆锥体
  3. 数据源3:添加一个AddActor2D,固定在视口左下角
  4. 数据源4:构造3D控件pointWidget,并添加观察者myCallback,监控pointWidget交互事件

注意:point符号化的过程中,一开始是没有符号的,所以圆锥体一开始不显示,交互时间开始后设置了point的值,点背符号化后有了圆锥体,Execute中关键代码:

//获取定义该点的多边形数据(包括点)。单个点和一个顶点组成 vtkPolyData。
pointWidget->GetPolyData(this->PolyData);//给this->PolyData / point 赋值,在多个管道中间中途修改值,修改后update修改过的管道,render
this->PositionActor->SetInput(text.str().c_str());

glyph的输入我把probefilter删了,直接用point数据,也是可以相同效果的,目前没有明白为什么要加一个vtkProbeFilter,理解的帮解答下,谢谢拉!!!

另一个需要重点关注的是需要区分以下接口接口

  vtkNew<vtkProbeFilter> probe;
  //指定一个数据对象作为输入。请注意,此方法不会建立管道连接。使用 SetInputConnection() 来 建立管道连接。
  probe->SetInputData(point);//输入: 此时的point值为空,需要事件内根据鼠标位置进行赋值
  //指定将在输入点进行探测的数据集。 
  //输入为输出提供几何图形(点和单元)、 而源点则通过探测(插值)生成标量、 矢量等。
  probe->SetSourceData(inputPolyData);//源: 

参考链接1
参考链接2
参考链接3

  vtkNew<vtkGlyph3D> glyph;
  // glyph->SetInputConnection(probe->GetOutputPort());//???不理解
  glyph->SetInputData(point); //此处直接使用point也可以达到效果,但是为什么非要用vtkProbeFilter 没有想通
  glyph->SetSourceConnection(cone->GetOutputPort());

参考链接1
参考链接2


prj name: Arbitrary3DCursor

#include <vtkActor.h>
#include <vtkCallbackCommand.h>
#include <vtkCommand.h>
#include <vtkConeSource.h>
#include <vtkGlyph3D.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPointWidget.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProbeFilter.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkXMLPolyDataReader.h>

#include <iostream>
#include <sstream>
#include <string>

// This does the actual work: updates the probe.
// Callback for the interaction.
class vtkmyPWCallback : public vtkCallbackCommand
{
public:
  vtkmyPWCallback() = default;

  static vtkmyPWCallback* New()
  {
    return new vtkmyPWCallback;
  }
  virtual void Execute(vtkObject* caller, unsigned long, void*)
  {
    vtkPointWidget* pointWidget = reinterpret_cast<vtkPointWidget*>(caller);
    //获取定义该点的多边形数据(包括点)。单个点和一个顶点组成 vtkPolyData。
    pointWidget->GetPolyData(this->PolyData);//给this->PolyData / point 赋值,在多个管道中间中途修改值,修改后update修改过的管道,render
    double position[3];
    pointWidget->GetPosition(position);
    std::ostringstream text;
    text << "cursor: " << std::fixed << std::setprecision(4) << position[0]
         << ", " << position[1] << ", " << position[2];
    this->PositionActor->SetInput(text.str().c_str());
    // this->CursorActor->VisibilityOn();
    std::cout << PolyData->GetNumberOfCells() << std::endl;
    std::cout << PolyData->GetNumberOfPoints() << std::endl;
    std::cout << PolyData->GetNumberOfPolys() << std::endl;

  }

  vtkPolyData* PolyData = nullptr;      //与传入的锥形有关
  //vtkActor* CursorActor = nullptr;    //可以不需要,如果需要控制显示隐藏状态,可以传入
  vtkTextActor* PositionActor = nullptr;//实时显示坐标状态
};

int main(int argc, char* argv[])
{
  vtkSmartPointer<vtkPolyData> inputPolyData;

  if (argc > 1)
  {
    vtkNew<vtkXMLPolyDataReader> reader;
    reader->SetFileName(argv[1]);
    reader->Update();
    inputPolyData = reader->GetOutput();
  }
  else
  {
    vtkNew<vtkSphereSource> sphereSource;
    sphereSource->SetPhiResolution(15);
    sphereSource->SetThetaResolution(15);
    sphereSource->Update();
    inputPolyData = sphereSource->GetOutput();
  }

  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkPolyData> point;

  //https://blog.csdn.net/liushao1031177/article/details/122860254
  //https://blog.csdn.net/yuyangyg/article/details/78165570
  //https://www.cnblogs.com/ankier/p/3166210.html
  /*
    在指定点位置采样数据值

    vtkProbeFilter 是一个过滤器,用于计算指定点位置的点属性(如标量、矢量等)。
        该过滤器有两个输入:输入和源。输入的几何结构通过过滤器。
        通过对源数据进行插值,在输入点位置计算出点属性。
        例如,我们可以根据体积(源数据)计算平面(指定为输入的平面)上的数据值。
        源数据的单元格数据会根据每个输入点所在的源单元格复制到输出端。
        如果源点数据和单元格数据中都存在同名数组,则只探查点数据中的数组。

    该过滤器可用于重新采样数据,或将一种数据集形式转换为另一种数据集形式。
        例如,非结构化网格(vtkUnstructuredGrid)可以用体积(三维 vtkImageData)进行探测,然后使用体积渲染技术将结果可视化。
        另一个例子:可以使用一条直线或曲线来探测数据,以生成沿该直线或曲线的 x-y 图。

    警告
    vtkProbeFilter 的一个关键算法组件是其查找包含探测点的单元格的方式。
        默认情况下,vtkDataSet::FindCell() 方法会被使用,该方法反过来使用 vtkPointLocator 来执行加速搜索。
        不过,在某些情况下,使用 vtkPointLocator 可能无法识别包围单元格。
        更稳健但更慢的方法是使用 vtkCellLocator 执行 FindCell() 操作(通过指定 CellLocatorPrototype)。
        最后,可以通过指定 vtkFindCellStrategy 的实例来配置更高级的搜索。
            (注意:图像数据探测从不使用定位器,因为查找包含的单元格是一个简单、快速的操作。
            因此指定 vtkFindCellStrategy 或单元格定位器原型没有任何作用)。
    vtkProbeFilter 一旦找到包含查询点的单元格,就会使用单元格的插值函数来执行插值/计算点属性。
        vtkPointInterpolator 支持多种广义内核,而 vtkSPHInterpolator 则支持多种 SPH 内核。
  */
  vtkNew<vtkProbeFilter> probe;
  //指定一个数据对象作为输入。请注意,此方法不会建立管道连接。使用 SetInputConnection() 来 建立管道连接。
  probe->SetInputData(point);//输入: 此时的point值为空,需要事件内根据鼠标位置进行赋值
  //指定将在输入点进行探测的数据集。 
  //输入为输出提供几何图形(点和单元)、 而源点则通过探测(插值)生成标量、 矢量等。
  probe->SetSourceData(inputPolyData);//源: 

  std::cout << point->GetNumberOfCells() << std::endl;
  std::cout << point->GetNumberOfPoints() << std::endl;
  std::cout << point->GetNumberOfPolys() << std::endl;

  // Create glyph.
  vtkNew<vtkConeSource> cone;
  cone->SetResolution(30);

  //https://blog.csdn.net/jigetage/article/details/86633156
  //https://www.cnblogs.com/vaughnhuang/p/17584058.html
  vtkNew<vtkGlyph3D> glyph;
  // glyph->SetInputConnection(probe->GetOutputPort());//???不理解
  glyph->SetInputData(point); //此处直接使用point也可以达到效果,但是为什么非要用vtkProbeFilter 没有想通
  glyph->SetSourceConnection(cone->GetOutputPort());
  glyph->SetVectorModeToUseVector();
  glyph->SetScaleModeToDataScalingOff();
  glyph->SetScaleFactor(inputPolyData->GetLength() * 0.1);

  vtkNew<vtkPolyDataMapper> glyphMapper;
  glyphMapper->SetInputConnection(glyph->GetOutputPort());

  vtkNew<vtkActor> glyphActor;
  glyphActor->SetMapper(glyphMapper);
  glyphActor->VisibilityOn();//point为空,没有glyph显示

  vtkNew<vtkPolyDataMapper> mapper;
  mapper->SetInputData(inputPolyData);

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetRepresentationToWireframe();
  actor->GetProperty()->SetColor(colors->GetColor3d("gold").GetData());

  vtkNew<vtkTextActor> textActor;
  textActor->GetTextProperty()->SetFontSize(12);
  textActor->SetPosition(10, 20);
  textActor->SetInput("cursor:");
  textActor->GetTextProperty()->SetColor(colors->GetColor3d("White").GetData());

  // Create the RenderWindow, Render1er and both Actors.
  vtkNew<vtkRenderer> ren1;
  vtkNew<vtkRenderWindow> renWin;
  renWin->AddRenderer(ren1);

  vtkNew<vtkRenderWindowInteractor> iren;
  iren->SetRenderWindow(renWin);

  // The SetInteractor method is how 3D widgets are associated with the render
  // window interactor. Internally, SetInteractor sets up a bunch of callbacks
  // using the Command/Observer mechanism (AddObserver()).
  vtkNew<vtkmyPWCallback> myCallback;
  myCallback->PolyData = point;
  //myCallback->PolyData = inputPolyData;
  //myCallback->CursorActor = glyphActor;
  myCallback->PositionActor = textActor;

  // The point widget is used probe the dataset.
  vtkNew<vtkPointWidget> pointWidget;
  pointWidget->SetInteractor(iren);
  pointWidget->SetInputData(inputPolyData);//指定移动范围
  pointWidget->AllOff();
  pointWidget->PlaceWidget();
  pointWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);

  ren1->AddActor(glyphActor);
  ren1->AddActor(actor);
  ren1->AddActor2D(textActor);//2D actor

  // Add the actors to the renderer, set the background and size.
  ren1->GradientBackgroundOn();
  ren1->SetBackground(colors->GetColor3d("SlateGray").GetData());
  ren1->SetBackground2(colors->GetColor3d("Wheat").GetData());

  renWin->SetSize(300, 300);
  renWin->SetWindowName("Arbitrary3DCursor");
  renWin->Render();
  pointWidget->On();

  // Render the image
  iren->Initialize();
  renWin->Render();

  iren->Start();

  return EXIT_SUCCESS;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177787.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】vector的介绍与使用

&#x1f9d1;‍&#x1f393;个人主页&#xff1a;简 料 &#x1f3c6;所属专栏&#xff1a;C &#x1f3c6;个人社区&#xff1a;越努力越幸运社区 &#x1f3c6;简 介&#xff1a;简料简料&#xff0c;简单有料~在校大学生一枚&#xff0c;专注C/C/GO的干货分…

9、鸿蒙应用桌面图标外观和国际化

一、项目资源目录 项目下的resoueces目录为资源配置目录&#xff0c;其中base为基础配置&#xff0c;即在任何语言环境下都会加载的资源&#xff0c; color.json&#xff1a;用于配置颜色&#xff0c;如页面的背景和文字的颜色。 string.json&#xff1a;用于设置文字&#…

好用的博客评论系统 Valine 使用及避坑指南

评论系统&#xff0c;即网站的一个小功能&#xff0c;展示评论内容和用户输入框。开源免费的评论系统可不多&#xff0c;原来很火的"多说"评论系统都关闭了&#xff0c;而Disqus又是国外的访问受限。无意间发现了Valine&#xff0c;挺不错的&#xff0c;分享给大家。…

UML建模图文详解教程——类图

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;《UML面向对象分析、建模与设计&#xff08;第2版&#xff09;》吕云翔&#xff0c;赵天宇 著 类图概述 类图用来描述系统内各种实体的类型以及不同…

关于软raid的实现及常见问题

RAID概念 磁盘阵列&#xff08;Redundant Arrays of Independent Disks&#xff0c;RAID&#xff09;&#xff0c;有“独立磁盘构成的具有冗余能力的阵列”之意。 磁盘阵列是由很多价格较便宜的磁盘&#xff0c;以硬件&#xff08;RAID卡&#xff09;或软件&#xff08;MDADM&…

【LeetCode刷题】--40.组合总和II

40.组合总和II 本题详解&#xff1a;回溯算法 class Solution {public List<List<Integer>> combinationSum2(int[] candidates, int target) {int len candidates.length;List<List<Integer>> res new ArrayList<>();if (len 0) {return re…

JSP内置对象

一、request对象 1、访问请求参数 2、在作用域中管理属性 3、获取Cookie 4、解决中文乱码 5、获取客户端信息 6、显示国际化信息 是一个javax.servlet.http.HttpServletRequest对象 request封装了用户浏览器提交的信息&#xff0c;因此可以调用相应的方法可以获取这些封…

VMware 16 Pro 安装以及下载

1、下载地址&#xff1a; https://www.aliyundrive.com/s/nj3PSD4TN9G 2、安装文件 右击打开 下一步 密钥&#xff1a;ZF3R0-FHED2-M80TY-8QYGC-NPKYF 到此&#xff0c;安装完毕

【python基础(三)】操作列表:for循环、正确缩进、切片的使用、元组

文章目录 一. 遍历整个列表1. 在for循环中执行更多操作2. 在for循环结束后执行一些操作 二. 避免缩进错误三. 创建数值列表1. 使用函数range()2. 使用range()创建数字列表3. 指定步长。4. 对数字列表执行简单的统计计算5. 列表解析 五. 使用列表的一部分-切片1. 切片2. 遍历切片…

基于单片机停车场环境监测系统仿真设计

**单片机设计介绍&#xff0c; 基于单片机停车场环境监测系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的停车场环境监测系统是一种利用单片机技术实现环境监测和数据处理的系统。它可以感知停车场的温湿…

什么是Jmeter?Jmeter使用的原理步骤是什么?

1.1 什么是 JMeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于 Web 应用测试&#xff0c;但后来扩展到其他测试领域。 它可以用于测试静态和动态资源&#xff0c;例如静态文件、Java 小服务程序、CGI 脚本…

6.基于蜻蜓优化算法 (DA)优化的VMD参数(DA-VMD)

代码原理 基于蜻蜓优化算法 (Dragonfly Algorithm, DA) 优化的 VMD 参数&#xff08;DA-VMD&#xff09;是指使用蜻蜓优化算法对 VMD 方法中的参数进行自动调优和优化。 VMD&#xff08;Variational Mode Decomposition&#xff09;是一种信号分解方法&#xff0c;用于将复杂…

Java如何获取泛型类型

泛型&#xff08;Generic&#xff09; 泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型&#xff0c;在实例化时作为参数指明这些类型。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Ada、Delphi、Eiffel、Java、C#、F#、Swift 和 Vis…

Unity开发之C#基础-File文件读取

前言 今天我们将要讲解到c#中 对于文件的读写是怎样的 那么没接触过特别系统编程小伙伴们应该会有一个疑问 这跟文件有什么关系呢&#xff1f; 我们这样来理解 首先 大家对电脑或多或少都应该有不少的了解吧 那么我们这些软件 都是通过变成一个一个文件保存在电脑中 我们才可以…

基于区域划分的GaN HEMT 准物理大信号模型

GaN HEMT器件的大信号等效电路模型分为经验基模型和物理基模型。经验基模型具有较高精度但参数提取困难&#xff0c;特别在GaN HEMT器件工艺不稳定的情况下不易应用。相比之下&#xff0c;物理基模型从器件工作机理出发&#xff0c;参数提取相对方便&#xff0c;且更容易更新和…

数字图像处理(冈萨雷斯)学习笔记

目录 一.机器视觉和计算机视觉二.图像处理基础1.什么是图像2.如何访问图像 三.图像仿射变换四.灰度变换 一.机器视觉和计算机视觉 机器视觉(Machine Vision,MV)和计算机视觉(Computer Vision&#xff0c;CV)的区别和联系&#xff1a; 机器视觉更注重广义图像信号(激光&#xff…

2023 年 亚太赛 APMCM ABC题 国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 以五一杯 A题为例子&#xff0c;以下是咱们做的一些想法呀&am…

01背包与完全背包学习总结

背包问题分类见下图 参考学习点击&#xff1a;代码随想录01背包讲解 01背包问题&#xff1a; 核心思路&#xff1a; 1、先遍历物品个数&#xff0c;再遍历背包容量。因为容量最先是最大的&#xff0c;往背包里放物品&#xff0c;所以背包容量在慢慢减少&#xff0c;但背包容量…

MySQL 8.2 Command Line Client打开时一闪而过闪退问题

MySQL8.2安装成功后&#xff0c;发现打开MySQL 8.0 Command Line Client时出现一闪而过&#xff0c;打不开的情况。 解决方案&#xff1a; 1、打开MySQL 8.2 Command Line Client文件位置 2、右键选择属性 3、复制它的目标 4、我复制下来的目标路径是这样的&#xff0c;"…

如何用cmd命令快速搭建FTP服务

环境&#xff1a; Win10专业版 问题描述&#xff1a; 如何用cmd命令快速搭建FTP服务 解决方案&#xff1a; 1.输入以下命令来安装IIS&#xff08;Internet Information Services&#xff09;&#xff1a; dism /online /enable-feature /featurename:IIS-FTPServer /all …