PCL及QT配置請移步點擊打開鏈接
前言
恭喜你已經入了qt和pcl的坑,這篇文章幫助你實現在qvtkWidget中點雲平面切割以及保存切割數據。
前提是你已經能成功讀取pcd文件,並且將qvtkWidget配置好(代碼中省略讀取pcd部分)
先放效果圖,如果是你想要的就繼續讀下去。
ps:初學,so只是將功能實現而已,若代碼風格以及完成功能方法不盡如人意請儘管提出建議~麼麼噠
class vtkIPWCallback : public vtkCommand
{
public:
static vtkIPWCallback *New()
{
return new vtkIPWCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkImplicitPlaneWidget2 *planeWidget =
reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
vtkImplicitPlaneRepresentation *rep =
reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
rep->GetPlane(this->Plane);
}
vtkIPWCallback() :Plane(0), Actor(0) {}
vtkPlane *Plane;
vtkActor *Actor;
};
//!!!!!!!!!!!!!!!!!!!!超重要的兩句,設置viewer的(試了很久纔出來的)
ui.qvtkWidget->SetRenderWindow(renderWindow);
viewer->setupInteractor(renderWindowInteractor, renderWindow);
void initial()
{
//添加cloud和viewer
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
//初始化
cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
viewer->addPointCloud(cloud, "cloud");
//初始化vtk
ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());
viewer->setCameraPosition(0, 0, -2, 0, -1, 0, 0);
ui.qvtkWidget->update();
}
int planeCut()
{
//input data
points = vtkSmartPointer<vtkPoints>::New();//添加點集
sourcePolyData = vtkSmartPointer<vtkPolyData>::New();//添加數據
glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();//過濾器
plane = vtkSmartPointer<vtkPlane>::New();//切割平面
clipper = vtkSmartPointer<vtkClipPolyData>::New();//
mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); //映射器,可以根據點、線、面構造圖形
actor = vtkSmartPointer<vtkActor>::New();//
backFaces = vtkSmartPointer<vtkProperty>::New();
renderer = vtkSmartPointer<vtkRenderer>::New();//繪製器,能夠繪製物體
renderWindow = vtkSmartPointer<vtkRenderWindow>::New();//繪製窗,提供繪製的平面
renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();//交互器
//!!!!!!!!!!!!!!!!!!!!超重要的兩句,設置viewer的
ui.qvtkWidget->SetRenderWindow(renderWindow);
viewer->setupInteractor(renderWindowInteractor, renderWindow);
//點雲數據輸入
for (size_t i = 0; i < cloud->points.size(); i++)
{
points->InsertNextPoint(cloud->points[i].x, cloud->points[i].y, cloud->points[i].z);
}
sourcePolyData->SetPoints(points);
#if VTK_MAJOR_VERSION <= 5
glyphFilter->SetInputConnection(polyData->GetProducerPort());
#else
glyphFilter->SetInputData(sourcePolyData); //完成點的傳遞
#endif
glyphFilter->Update();
//裁剪設置
clipper->SetClipFunction(plane);
clipper->InsideOutOn();
clipper->SetInputConnection(glyphFilter->GetOutputPort());
clipper->Update();
// 映射和動作
mapper->SetInputConnection(clipper->GetOutputPort());
actor->SetMapper(mapper);
backFaces->SetDiffuseColor(0.8275, 0.8275, 0.8275);
actor->SetBackfaceProperty(backFaces);
// 繪製窗口
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
//交互器
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
// 回調
vtkSmartPointer<vtkIPWCallback> myCallback =
vtkSmartPointer<vtkIPWCallback>::New();
myCallback->Plane = plane;
myCallback->Actor = actor;
//提前於planewidget設置
vtkSmartPointer<vtkImplicitPlaneRepresentation> rep =
vtkSmartPointer<vtkImplicitPlaneRepresentation>::New();
rep->SetPlaceFactor(1.25);
rep->PlaceWidget(actor->GetBounds());
rep->SetNormal(plane->GetNormal());
rep->SetOrigin(0, 0, 0);
vtkSmartPointer<vtkImplicitPlaneWidget2> planeWidget =
vtkSmartPointer<vtkImplicitPlaneWidget2>::New();
planeWidget->SetInteractor(renderWindowInteractor);
planeWidget->SetRepresentation(rep);
planeWidget->AddObserver(vtkCommand::InteractionEvent, myCallback); //對觀察到的事件響應
// 繪製
renderWindowInteractor->Initialize();
renderWindow->Render();
planeWidget->On();
// 鼠標交互
renderWindowInteractor->Start();
//過濾被裁剪部分
////////////////////////////////////////
vtkSmartPointer<vtkIdFilter> cellIdFilter =
vtkSmartPointer<vtkIdFilter>::New();
cellIdFilter->SetInputConnection(clipper->GetOutputPort());
cellIdFilter->SetCellIds(true);
cellIdFilter->SetPointIds(false);
cellIdFilter->SetIdsArrayName("CellIds");
cellIdFilter->Update();
//將過濾部分保存ply
//////////////////////////////////////////////////////////////////
vtkSmartPointer<vtkPLYWriter> writer = vtkSmartPointer<vtkPLYWriter>::New();
std::string filename = "temp/mesh.ply";
#if VTK_MAJOR_VERSION <= 5
writer->SetInput(dataSet);
#else
writer->SetInputData(cellIdFilter->GetOutput());
#endif
writer->SetFileName(filename.c_str());
writer->Write();
//格式轉換,先將ply轉爲vtk,再轉vtk爲pcdpcl::PolygonMesh mesh;
vtkSmartPointer<vtkPolyData> poly = vtkSmartPointer<vtkPolyData>::New();
pcl::io::loadPolygonFilePLY("temp/mesh.ply", mesh);
pcl::io::mesh2vtk(mesh, poly);
pcl::io::vtkPolyDataToPointCloud(poly, *cloud);
viewer->updatePointCloud(cloud, "cloud");
ui.qvtkWidget->update();
//更新上一步剪切的數據爲新的input
glyphFilter->SetInputData(poly);
glyphFilter->Update();return EXIT_SUCCESS;}