【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点

这篇具有很好参考价值的文章主要介绍了【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。

基于读取出来的 STL 模型,实现当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点。

详细流程为:点击 Select 按钮,鼠标具备选择的功能。当按下 Select Done 鼠标删除掉此功能。

【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点,Visual Studio,c++,计算机外设,开发语言


主要是通过两个类和一个函数来实现的:

  • class PointPickedSignal : public QObject
  • class MouseInteractorCommand : public vtkCommand
  • void A::on_pushButtonSelected_clicked()
  • void A::onPointPicked(double* pos)

下边依次分析。

class PointPickedSignal : public QObject

class PointPickedSignal : public QObject
{
    Q_OBJECT
public:
    PointPickedSignal(QObject* parent = nullptr) : QObject(parent) {}

signals:
    void pointPicked(double* pos);
};

这个类继承自 QObject 类,用于实现一个名为 pointPicked 的 Qt 信号,当一个点被选中时发出该信号。这个信号将被用于通知其他对象选中的点的坐标。

class MouseInteractorCommand : public vtkCommand

class MouseInteractorCommand : public vtkCommand
{
public:
    vtkTypeMacro(MouseInteractorCommand, vtkCommand);

    static MouseInteractorCommand* New()
    {
        return new MouseInteractorCommand;
    }

    virtual void Execute(vtkObject* caller, unsigned long eventId, void* vtkNotUsed(callData))
    {
        vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
        int* clickPos = interactor->GetEventPosition();

        vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
        picker->SetTolerance(0.0005);

        if (picker->Pick(clickPos[0], clickPos[1], 0, interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()))
        {
            double* pos = picker->GetPickPosition();
            memcpy(pickedPoint, pos, sizeof(double) * 3);
            emit signal->pointPicked(pickedPoint);
        }
    }

    double pickedPoint[3];
    PointPickedSignal* signal; // this will emit the pointPicked signal when a point is picked
};

这个类继承自 vtkCommand 类,其功能是监听鼠标左键的点击事件。当用户点击鼠标左键时,会触发 Execute 方法。在这个方法中,代码首先从事件的发起者中获取交互器,并从交互器中获取点击的位置。然后,它创建一个 vtkCellPicker 对象并尝试拾取点击位置的点。如果成功拾取了一个点,它将获取该点的坐标,并使用 memcpy 将这些坐标复制到 pickedPoint 数组中。最后,它发出 pointPicked 信号,将选中的点的坐标作为参数。

void A::on_pushButtonSelected_clicked()

void A::on_pushButtonSelected_clicked() {
    ui.textBrowser->insertPlainText("Button Clicked");

    PointPickedSignal* signal = new PointPickedSignal(this);
    
    vtkSmartPointer<MouseInteractorCommand> command = vtkSmartPointer<MouseInteractorCommand>::New();
    command->signal = signal;
    
    ui.qvtkWidget->interactor()->AddObserver(vtkCommand::LeftButtonPressEvent, command);

    QEventLoop loop;
    connect(signal, &PointPickedSignal::pointPicked, this, &A::onPointPicked);
    connect(signal, &PointPickedSignal::pointPicked, &loop, &QEventLoop::quit);
    loop.exec();

    onPointPicked(command->pickedPoint);
}

这个方法首先创建一个 PointPickedSignal 对象和一个 MouseInteractorCommand 对象。然后,它将 PointPickedSignal 对象赋值给 MouseInteractorCommand 对象的 signal 成员,然后将这个 MouseInteractorCommand 对象添加为 QVTKWidget 对象的交互器的观察者,这样当交互器收到左键按下事件时,就会执行 MouseInteractorCommand 对象的 Execute 方法。

然后,这个方法创建一个 QEventLoop 对象并开始执行事件循环。在事件循环中,当 pointPicked 信号被发出时,它将调用 A::onPointPicked() 方法,并结束事件循环。

void A::onPointPicked(double* pos)

void A::onPointPicked(double* pos) {
    ui.textBrowser->insertPlainText(QString("Point picked: %1 %2 %3\n").arg(pos[0]).arg(pos[1]).arg(pos[2]));
    ui.textBrowser->moveCursor(QTextCursor::End);
    mandibleActor->SetOrigin(pos);
}

当这个方法被调用时,它将在文本浏览器中显示选中的点的坐标,并将这个点设置为模型的旋转原点。

通过这种方式,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点。


完整版代码如下:文章来源地址https://www.toymoban.com/news/detail-628424.html

A.h

// A.h
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_A.h"

#include <vtkSmartPointer.h>
#include <vtkSTLReader.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

#include <vtkCellPicker.h>
#include <vtkCommand.h>
#include <vtkObjectFactory.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkRendererCollection.h>
#include <vtkPropPicker.h>
#include <QObject>

#include <qtimer.h>

class A : public QMainWindow
{
    Q_OBJECT

public:
    A(QWidget* parent = nullptr);
    ~A();

private slots:
    void on_pushButtonSelect_clicked();
    void on_pushButtonSelDone_clicked();
    void onPointPicked(double* pos);

    void rotate();

private:
    Ui::AClass ui;

    void initVTK();

    vtkSmartPointer<vtkActor> actor;
    vtkSmartPointer<vtkRenderer> renderer;
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow;

    QTimer* timer;
};

class PointPickedSignal : public QObject
{
    Q_OBJECT
public:
    PointPickedSignal(QObject* parent = nullptr) : QObject(parent) {}

signals:
    void pointPicked(double* pos);
};

class MouseInteractorCommand : public vtkCommand
{
public:
    vtkTypeMacro(MouseInteractorCommand, vtkCommand);

    static MouseInteractorCommand* New()
    {
        return new MouseInteractorCommand;
    }

    virtual void Execute(vtkObject* caller, unsigned long eventId, void* vtkNotUsed(callData))
    {
        vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
        int* clickPos = interactor->GetEventPosition();

        vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
        picker->SetTolerance(0.0005);

        if (picker->Pick(clickPos[0], clickPos[1], 0, interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()))
        {
            double* pos = picker->GetPickPosition();
            memcpy(pickedPoint, pos, sizeof(double) * 3);
            emit signal->pointPicked(pickedPoint);
        }
    }

    double pickedPoint[3];
    PointPickedSignal* signal; // this will emit the pointPicked signal when a point is picked
};

A.cpp

// A.cpp
#include "A.h"



A::A(QWidget* parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    // 配置 VTK 的初始设置
    initVTK();

    // 定时器,50ms 更新触发一次 checkPositionChange()
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(rotate()));
    timer->start(100);
}

A::~A()
{
}

void A::initVTK()
{
    // 读取 STL 文件
    vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName("skull_50.stl"); // 请替换为你的 STL 文件路径
    reader->Update();

    // 创建映射器和演员
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(reader->GetOutputPort());

    actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    // 创建渲染器
    renderer = vtkSmartPointer<vtkRenderer>::New();
    // 添加演员到渲染器
    renderer->AddActor(actor);

    // 创建渲染窗口和渲染窗口交互器
    renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);

    // 添加到 qvtkWidget 控件中显示
    ui.qvtkWidget->setRenderWindow(renderWindow);

}

void A::on_pushButtonSelect_clicked() {
    ui.textBrowser->insertPlainText("Select button clicked!\n");

    PointPickedSignal* signal = new PointPickedSignal(this);
    vtkSmartPointer<MouseInteractorCommand> command = vtkSmartPointer<MouseInteractorCommand>::New();
    command->signal = signal;
    ui.qvtkWidget->interactor()->AddObserver(vtkCommand::LeftButtonPressEvent, command);

    QEventLoop loop;
    connect(signal, &PointPickedSignal::pointPicked, this, &A::onPointPicked);
    connect(signal, &PointPickedSignal::pointPicked, &loop, &QEventLoop::quit);
    loop.exec();

    onPointPicked(command->pickedPoint);
}

void A::onPointPicked(double* pos) {
    ui.textBrowser->insertPlainText(QString("Point picked: %1 %2 %3\n").arg(pos[0]).arg(pos[1]).arg(pos[2]));
    ui.textBrowser->moveCursor(QTextCursor::End);
    actor->SetOrigin(pos);
}

void A::on_pushButtonSelDone_clicked() {
    ui.textBrowser->insertPlainText("Selection done, restore the default interactor style.\n");

    // 移除左键按下事件的观察者
    ui.qvtkWidget->interactor()->RemoveObservers(vtkCommand::LeftButtonPressEvent);

    // 恢复默认的交互器样式。
    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    ui.qvtkWidget->interactor()->SetInteractorStyle(style);
}

void A::rotate()
{
    actor->RotateX(5);
    renderWindow->Render();
}

Ref.

  1. 骷髅3D打印3D模型

到了这里,关于【VTK】基于读取出来的 STL 模型,当用户点击鼠标左键时,程序将获取点击位置的点,显示其坐标,并设置它为模型的旋转原点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VTK——设置交互样式上的鼠标回调函数

    VTKPointPickerInteractorStyle是一个自定义的交互样式类,它是VTK库中vtkInteractorStyleTrackballCamera类的子类。VTK(Visualization Toolkit)是一个开源的,跨平台的库,用于处理、渲染和视觉化科学数据。它包括一系列的类和方法用于3D计算机图形、图像处理和可视化。 vtkInteractorStyleTrackba

    2024年02月10日
    浏览(40)
  • open3d,读取stl/ply/obj/off/gltf/glb三维模型,并转换成点云,保存

    可以自己用建模软件建立一个模型 本案例使用模型的下载地址 可以从free3d免费下载,无需注册 效果: 效果: 均匀采样会在表面出现采样点聚集的现象,open3d实现了一种基于poisson_disk方法的采样,能实现表面的均匀采样 原理 :参数umber_of_points是最终采样的点数量,实际会先

    2024年02月11日
    浏览(41)
  • VTK & QT QVTKWidget自定义鼠标和键盘交互事件

    目录 一、问题描述 二、代码实现 1. 自定义鼠标交互事件 2. 移除默认鼠标交互监听事件,塞入自定义监听事件 在使用VTK显示的过程中,通常会使用QT来进行界面设计。这里通常使用QVTKWidget将VTK的渲染窗口显示到QT的组件中。 QVTKWidget组件自带交互器vtkRenderWindowInteractor和Rende

    2024年02月14日
    浏览(40)
  • 【FastCAE源码阅读5】使用VTK实现鼠标拾取对象并高亮

    鼠标拾取对象是很多软件的基本功能。FastCAE的拾取比较简单,是通过VTK实现的。 对几何而言,拾取类型切换在工具栏上,单击后再来单击视图区对象进行拾取,拾取后的对象会高亮显示。效果如下图: 一、拾取对象 拾取对象是在PropPickerInteractionStyle类实现的,该类是vtkInt

    2024年02月02日
    浏览(40)
  • 【Python VTK】读取二维序列医学图像分割结果并进行三维重建

    最近在开发过程中遇到了这样的问题: 在医学图像开发过程中,我们将医学图像通过 深度学习 算法进行分割,现在想要 通过这一套二维图像进行三维重构 。 以下是分割结果: 图一:前列腺核磁图像分割结果 图一:前列腺核磁图像分割结果 图一:前列腺核磁图像分割结果

    2024年02月01日
    浏览(36)
  • 基于Vue3实现鼠标按下某个元素进行拖动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

    其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度,然后再用CSS赋值就实现该效果了。

    2024年02月12日
    浏览(30)
  • 基于Vue3实现鼠标按下某个元素进行移动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

    其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度,然后再用CSS赋值就实现该效果了。

    2024年02月15日
    浏览(37)
  • python VTK PyQt5 VTK环境搭建 创建 渲染窗口及三维模型,包含 三维模型交互;

      目录 Part1. VTK 介绍 Part2. PyQt5 VTK环境搭建 安装Anaconda 自带Python Anaconda下载 安装PyQt5 安装 VTK Part3 :PyQt VTK 结合样例: Part1. VTK 介绍 VTK(visualization toolkit)是一个开源的免费软件系统,主要用于三维计算机图形学、图像处理和可视化。Vtk 是在面向对象原理的基础上设计和实现的

    2024年02月11日
    浏览(36)
  • NIPS2022|南京大学提出基于点击后行为的广义延迟反馈模型

    Generalized Delayed Feedback Model with Post-Click Information in Recommender Systems Jia-Qi Yang De-Chuan Zhan Nanjing University https://proceedings.neurips.cc/paper_files/paper/2022/file/a7f90da65dd41d699d00e95700e6fa1e-Paper-Conference.pdf 转化率预估(比如预测某个用户购买某个商品的概率)在机器学习推荐系统中是一个基本问

    2024年02月05日
    浏览(30)
  • VTK————3D模型的旋转、交互、透明度设置

    旋转模型的话可以用到以下例程,但是每次设置选择坐标时,都是累加的。可以通过SetOrientation来将模型方向设为初试方向。如果三个坐标都使用较大值来进行旋转,那么由于累加的特性。模型会在空间内进行大幅度的旋转和位移,这是需要注意的。 也可以通过设置interacto

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包