三维控件中定位一个点_vtkPointWidget

news2025/1/17 1:03:07

开发环境:

  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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++ std::variant用法

std::variant Union类型的问题&#xff1a; 无法知道当前使用的类型是什么union无法自动调用底层数据成员的析构函数。联合体无法对其内部的数据属性的生命周期的全面支持&#xff0c;因为当外部代码调用Union时在切换类型&#xff0c;它无法做到对当前使用的对象&#xff0c…

解决第三方使用iframe内嵌页面时无法正常登录访问的问题

1. 问题描述 在做项目的时候&#xff0c;可能会遇到需要内嵌第三方页面或者第三方软件厂商内嵌我们自己做的web页面&#xff08;这里说的内嵌方式是用iframe的方式&#xff09;&#xff0c;当在使用最新版本的“谷歌浏览器”时就会出现无法正常登录的问题&#xff0c;内嵌的页…

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

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

ubuntu借助overlay方案实现重启自动还原

配置重启还原OS 首先&#xff1a;sudo apt install overlayroot 安装一下软件 然后编辑配置文件&#xff1a;/etc/overlayroot.conf * overlayroottmpfs or overlayroottmpfs:PARAMETERS write all changes to a temporary (ram only) backing device A tmpfs mount will …

C语言每日一题(35)有效的括号

力扣网 20 有效的括号 题目描述 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右…

每日一题(LeetCode)----链表--分隔链表

每日一题(LeetCode)----链表–分隔链表 1.题目&#xff08;86. 分隔链表&#xff09; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初…

redis运维(十五) 集合

一 集合 ① 概念 集合的元素在redis里面的世界是member集合&#xff1a; setset集合当中不允许重复的元素&#xff0c;而且set集合当中元素是没有顺序的,不存在元素下标 ② sadd、smembers、srem ③ sismember、srandmember、spop、scard spop 命令用于移除集合中的指定 …

数据结构学习笔记——多维数组、矩阵与广义表

目录 一、多维数组&#xff08;一&#xff09;数组的定义&#xff08;二&#xff09;二维数组&#xff08;三&#xff09;多维数组的存储&#xff08;四&#xff09;多维数组的下标的相关计算 二、矩阵&#xff08;一&#xff09;特殊矩阵和稀疏矩阵&#xff08;二&#xff09;…

前端CSS实现响应式TimeLine效果(附源码)

文章目录 纯CSS搭建&#xff0c;先上效果图&#xff08;附有源码&#xff09;视图层 index.htmlindex.css 公用样式文件Main.css 主要的样式文件 纯CSS搭建&#xff0c;先上效果图&#xff08;附有源码&#xff09; 本效果为纯CSS搭建&#xff0c;适配移动端和PC端&#xff01…

FreeRTOS列表和列表项

FreeRTOS内核调度使用了大量的列表&#xff08;list&#xff09;和列表项&#xff08;listitem&#xff09;数据结构。它的源码中涉及到很多列表的操作&#xff0c;对于FreeRTOS来说&#xff0c;列表就是它最基础的一部分&#xff0c;列表被用作FreeRTOS调度器使用&#xff0c;…

SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示

SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值&#xff0c;分别。以下是它们的用法和示例&#xff1a; MIN() 函数 MIN()函数返回所选列的最小值。 示例&#xff1a; 查找Products表中的最低价格&#xff1a; SELECT MIN(Price) F…

搜维尔科技:电影中面部动画的演变,Faceware面部捕捉成后起之秀

面部动画是电影中角色表演的一个重要方面&#xff0c;尤其是在严重依赖电子动画、化妆效果和动作捕捉系统的奇幻电影中。在《龙与地下城&#xff1a;盗贼荣耀》电影中&#xff0c;龙裔角色的面部动画是一个复杂的系统&#xff0c;使该生物在大屏幕上栩栩如生。该系统依赖于一种…

【代码随想录】算法训练计划30

【代码随想录】算法训练计划30 1、51. N 皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;…

【鸿蒙生态千帆起】HarmonyOS 系统级地图与位置服务,赋能广大开发者

在"与 HarmonyOS 同行&#xff0c;开放生态&#xff0c;共赢未来"为主题的 HUAWEI Developer Day&#xff08;简称 HDD&#xff09;沙龙中&#xff0c;Petal Maps 为开发者们带来了在 HarmonyOS 下地图领域的最新技术探索与实践成果。 得益于 HarmonyOS 一次开发多端…

小程序存在优惠卷遍历,但是歪了

进入小程序&#xff0c;因为是一个小商城&#xff0c;所以照例先查看收货地址是否存在越权&#xff0c;以及能否未授权访问&#xff0c;但是发现不存在这些问题&#xff0c;所以去查看优惠卷 进入领券中心&#xff0c;点击领取优惠券时抓包 发现数据包&#xff0c;存在敏感参数…

【java】想要限制每次查询的结果集不能超过10000行,该如何实现?

文章目录 前言 前言 对于一些Saas化软件&#xff0c;当某个租户在执行查询SQL时&#xff0c;如果查询条件出现了BUG&#xff0c;导致去查了所有租户的数据&#xff0c;这种情况是非常严重的&#xff0c;此时就需要在架构层面做限制&#xff0c;禁止一些特殊SQL的执行&#xff…

.Net6使用WebSocket与前端进行通信

1. 创建类WebSocketTest&#xff1a; using System.Net.WebSockets; using System.Text;namespace WebSocket.Demo {public class WebSocketTest{//当前请求实例System.Net.WebSockets.WebSocket socket null;public async Task DoWork(HttpContext ctx){socket await ctx.We…

还记得高中生物书上的莫斯密码吗?利用Python破解摩斯密码的代码示例!

文章目录 前言摩尔斯电码Python实现摩斯密码对照表加密解密测试 完整代码总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Py…

数学建模之拟合及其代码

发现新天地&#xff0c;欢迎访问Cr不是铬的个人网站 引言 与插值问题不同&#xff0c;在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数&#xff08;曲线&#xff09;&#xff0c;使得该曲线在某种准则下与所有的数据点最为接近&#xff0c;即曲线拟合…

【Docker】Docker安装Nginx配置静态资源

1.下载镜像 2.创建nginx配置文件 3.创建nginx容器运行 4.配置nginx静态资源 1.下载镜像 Dockerhub官网&#xff1a;Docker docker pull nginx docker pull nginx下载最新版本 默认latest 下载指定版本docker pull nginx:xxx 2.创建nginx配置文件 启动容器之前要创建nginx…