知識(shí)不是單獨(dú)的,一定是成體系的。更多我的個(gè)人總結(jié)和相關(guān)經(jīng)驗(yàn)可查閱這個(gè)專(zhuān)欄:Visual Studio。
基于讀取出來(lái)的 STL 模型,實(shí)現(xiàn)當(dāng)用戶(hù)點(diǎn)擊鼠標(biāo)左鍵時(shí),程序?qū)@取點(diǎn)擊位置的點(diǎn),顯示其坐標(biāo),并設(shè)置它為模型的旋轉(zhuǎn)原點(diǎn)。
詳細(xì)流程為:點(diǎn)擊 Select
按鈕,鼠標(biāo)具備選擇的功能。當(dāng)按下 Select Done
鼠標(biāo)刪除掉此功能。
主要是通過(guò)兩個(gè)類(lèi)和一個(gè)函數(shù)來(lái)實(shí)現(xiàn)的:
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);
};
這個(gè)類(lèi)繼承自 QObject
類(lèi),用于實(shí)現(xiàn)一個(gè)名為 pointPicked
的 Qt 信號(hào),當(dāng)一個(gè)點(diǎn)被選中時(shí)發(fā)出該信號(hào)。這個(gè)信號(hào)將被用于通知其他對(duì)象選中的點(diǎn)的坐標(biāo)。
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
};
這個(gè)類(lèi)繼承自 vtkCommand
類(lèi),其功能是監(jiān)聽(tīng)鼠標(biāo)左鍵的點(diǎn)擊事件。當(dāng)用戶(hù)點(diǎn)擊鼠標(biāo)左鍵時(shí),會(huì)觸發(fā) Execute
方法。在這個(gè)方法中,代碼首先從事件的發(fā)起者中獲取交互器,并從交互器中獲取點(diǎn)擊的位置。然后,它創(chuàng)建一個(gè) vtkCellPicker
對(duì)象并嘗試拾取點(diǎn)擊位置的點(diǎn)。如果成功拾取了一個(gè)點(diǎn),它將獲取該點(diǎn)的坐標(biāo),并使用 memcpy
將這些坐標(biāo)復(fù)制到 pickedPoint
數(shù)組中。最后,它發(fā)出 pointPicked
信號(hào),將選中的點(diǎn)的坐標(biāo)作為參數(shù)。
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);
}
這個(gè)方法首先創(chuàng)建一個(gè) PointPickedSignal
對(duì)象和一個(gè) MouseInteractorCommand
對(duì)象。然后,它將 PointPickedSignal
對(duì)象賦值給 MouseInteractorCommand
對(duì)象的 signal 成員,然后將這個(gè) MouseInteractorCommand
對(duì)象添加為 QVTKWidget
對(duì)象的交互器的觀察者,這樣當(dāng)交互器收到左鍵按下事件時(shí),就會(huì)執(zhí)行 MouseInteractorCommand
對(duì)象的 Execute
方法。
然后,這個(gè)方法創(chuàng)建一個(gè) QEventLoop
對(duì)象并開(kāi)始執(zhí)行事件循環(huán)。在事件循環(huán)中,當(dāng) pointPicked
信號(hào)被發(fā)出時(shí),它將調(diào)用 A::onPointPicked()
方法,并結(jié)束事件循環(huán)。
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);
}
當(dāng)這個(gè)方法被調(diào)用時(shí),它將在文本瀏覽器中顯示選中的點(diǎn)的坐標(biāo),并將這個(gè)點(diǎn)設(shè)置為模型的旋轉(zhuǎn)原點(diǎn)。
通過(guò)這種方式,當(dāng)用戶(hù)點(diǎn)擊鼠標(biāo)左鍵時(shí),程序?qū)@取點(diǎn)擊位置的點(diǎn),顯示其坐標(biāo),并設(shè)置它為模型的旋轉(zhuǎn)原點(diǎn)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-628424.html
完整版代碼如下:文章來(lái)源地址http://www.zghlxwxcb.cn/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 的初始設(shè)置
initVTK();
// 定時(shí)器,50ms 更新觸發(fā)一次 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"); // 請(qǐng)?zhí)鎿Q為你的 STL 文件路徑
reader->Update();
// 創(chuàng)建映射器和演員
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// 創(chuàng)建渲染器
renderer = vtkSmartPointer<vtkRenderer>::New();
// 添加演員到渲染器
renderer->AddActor(actor);
// 創(chuàng)建渲染窗口和渲染窗口交互器
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);
// 恢復(fù)默認(rèn)的交互器樣式。
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
ui.qvtkWidget->interactor()->SetInteractorStyle(style);
}
void A::rotate()
{
actor->RotateX(5);
renderWindow->Render();
}
Ref.
- 骷髏3D打印3D模型
到了這里,關(guān)于【VTK】基于讀取出來(lái)的 STL 模型,當(dāng)用戶(hù)點(diǎn)擊鼠標(biāo)左鍵時(shí),程序?qū)@取點(diǎn)擊位置的點(diǎn),顯示其坐標(biāo),并設(shè)置它為模型的旋轉(zhuǎn)原點(diǎn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!