赞
踩
最近需要对stl三维模型表面的点进行拾取,然后也需要点云配准,所以之前都是把stl转成pcd,用pcl瞎搞。pcl里也也能实现对点云的点拾取,但是pcl的viewer显示点云没有光源(PCL小白,不知道能不能设置,我是没找到的),这就看不到三维模型的表面特征了(我要根据表面特征手动选点)。网上看到的资料都是用VTK,就研究一下(VTK小白中的小白,有不对的地方请谅解)。
先贴参考:
https://blog.csdn.net/qq_42570058/article/details/107914377:看完可以对vtk有个大概的了解
https://blog.csdn.net/webzhuce/article/details/72802322:了解一下vtk里的拾取类
https://blog.csdn.net/shenziheng1/article/details/54959201:三维模型点拾取,但是对于复杂的三维模型,可能会拾取错误(即选到了背面的点,这里仔细看了vtkPointPicker的描述,拾取错误的原因应该是是背面的点离射线更近,想象一下射线重三角面片中穿过)上面是我个人的理解,不知道对不对。
https://blog.csdn.net/asimov_liu/article/details/78748785:拾取点/显示当前点选点并删除上次的点选点
https://blog.csdn.net/q610098308/article/details/125421795:拾取三角面片。这里我们可以参考使用vtkCellPicker,就应该可以避免选到背面了(我的理解是射线碰到三角面片直接返回信息)。
然后参考上面拾取三角面片的例子,我们这里不显示三角面片,用一个球代替显示,达到所谓的点拾取。这了我读的是vtk文件,stl得加个头文件
#include <vtkSTLReader.h>
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName("1.stl");
reader->Update();
#include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2); VTK_MODULE_INIT(vtkRenderingFreeType); #include <vtkSmartPointer.h> #include <vtkSphereSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkDataSetMapper.h> #include <vtkCellPicker.h> #include <vtkSelectionNode.h> #include <vtkSelection.h> #include <vtkRendererCollection.h> #include <vtkExtractSelection.h> #include <vtkObjectFactory.h> #include <vtkNamedColors.h> #include <vtkUnstructuredGrid.h> #include <vtkNamedColors.h> #include <vtkPolyDataReader.h> // Catch mouse events class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: //double picked[3];//选取的点坐标 double* worldPosition; static MouseInteractorStyle* New(); MouseInteractorStyle() { last_picked_actor = NULL; selectedMapper = vtkSmartPointer<vtkDataSetMapper>::New(); selectedActor = vtkSmartPointer<vtkActor>::New(); } virtual void OnLeftButtonDown() override { vtkNew<vtkNamedColors> colors; // Get the location of the click (in window coordinates) int* pos = this->GetInteractor()->GetEventPosition(); vtkNew<vtkCellPicker> picker; picker->SetTolerance(0.0005); // Pick from this location. picker->Pick(pos[0], pos[1], 0, this->GetDefaultRenderer()); worldPosition = picker->GetPickPosition(); std::cout << "Cell id is: " << picker->GetCellId() << std::endl; if (picker->GetCellId() != -1) { std::cout << "Pick position is: (" << worldPosition[0] << ", "<< worldPosition[1] << ", " << worldPosition[2] << ")" << endl; //如果之前选择了其他点,删除上一次的标记点 if (this->last_picked_actor) { this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->RemoveActor(last_picked_actor); //last_picked_actor->Delete(); //last_picked_actor=vtkActor::New(); } //获取此次的标记点 this->last_picked_actor = GetActor(); if (this->last_picked_actor) { //标记出来, this->last_picked_actor->SetScale(2.0); this->last_picked_actor->GetProperty()->SetColor(1.0, 0.0, 0.0); this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(this->last_picked_actor); } } // Forward events vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); } vtkSmartPointer<vtkPolyData> Data; vtkSmartPointer<vtkDataSetMapper> selectedMapper; vtkSmartPointer<vtkActor> selectedActor; private: vtkActor* last_picked_actor; inline vtkActor* GetActor() { vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->Update(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(sphereSource->GetOutputPort()); vtkActor* actor = vtkActor::New(); actor->SetMapper(mapper); actor->SetPosition(worldPosition); return actor; } }; vtkStandardNewMacro(MouseInteractorStyle); int main(int, char* []) { vtkNew<vtkNamedColors> colors; vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New(); reader->SetFileName("Mesh.vtk"); reader->Update(); vtkNew<vtkPolyDataMapper> mapper; mapper->SetInputConnection(reader->GetOutputPort()); vtkNew<vtkActor> actor; actor->GetProperty()->SetColor(colors->GetColor3d("SeaGreen").GetData()); actor->SetMapper(mapper); vtkNew<vtkRenderer> renderer; renderer->AddActor(actor); renderer->ResetCamera(); renderer->SetBackground(colors->GetColor3d("PaleTurquoise").GetData()); vtkNew<vtkRenderWindow> renderWindow; renderWindow->Render(); renderWindow->AddRenderer(renderer); renderWindow->SetWindowName("CellPicking"); vtkNew<vtkRenderWindowInteractor> renderWindowInteractor; renderWindowInteractor->SetRenderWindow(renderWindow); renderWindowInteractor->Initialize(); // Set the custom stype to use for interaction. vtkNew<MouseInteractorStyle> style; style->SetDefaultRenderer(renderer); style->Data = reader->GetOutput(); renderWindowInteractor->SetInteractorStyle(style); renderWindow->Render(); renderWindowInteractor->Start(); return EXIT_SUCCESS; }
补充-----------2024.1.16---------------
使用QT+VTK显示时,导入自定义交互后,关闭qt主窗口后,程序仍在运行问题:
//VTK交互器
vtkNew<vtkRenderWindowInteractor> interactor;
interactor->SetRenderWindow(renderWindow);
// 设置交互器样式
vtkNew<vtkMyInteractorStyle_Single_point_pickup> style;
style->SetDefaultRenderer(renderer);
//导入自定义交互
interactor->SetInteractorStyle(style);
interactor->Initialize();
interactor->Start();
Start()后应该是会启动一个线程进行循环。在关闭qt主窗口后,这个交互器的循环仍在执行,导致整个程序仍在运行。
解决:在qt窗口关闭时执行以下程序(即退出自定义交互的循环
if (interactor) interactor->ExitCallback();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。