QT+VTK+PCL實現交互式點雲平面切割

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爲pcd

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


 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章