VTK+Qt三维可视化系列应用
第二篇 使用BoxWidget包围盒模拟平面切割
前言
对STL模型的包围盒进行交互从而对模型的“切割”,加引号是因为其实只是设置了类似于摄像机的裁切平面,使视觉上只能看见包围盒内的一部分物体
一、载入模型
导入自定义的STL模型,是用3DBuilder随便画的,便于观察效果
主要代码:
string fileName = "file.stl";
vtkSmartPointer<vtkSTLReader>reader = vtkSTLReader::New();
reader->SetFileName(fileName.c_str());
reader->Update();
m_sourcepolydata = reader->GetOutput();
vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New();
stripper->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> polydatamapper = vtkSmartPointer<vtkPolyDataMapper>::New();
polydatamapper->SetInputConnection(stripper->GetOutputPort());
actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(polydatamapper);
actor->GetProperty()->SetOpacity(0.5);
renderer->AddActor(actor);
renderer->SetBackground(0.1,0.2,0.3);
renderer->ResetCamera();
vtkSmartPointer<vtkAxesActor> Axes = vtkSmartPointer<vtkAxesActor>::New(); //加个坐标轴
vtkOrientationMarkerWidget* widget = vtkOrientationMarkerWidget::New();
widget->SetInteractor(interactor);
widget->SetOrientationMarker(Axes);
widget->SetOutlineColor(1, 1, 1);
widget->SetViewport(0, 0, 0.2, 0.2);
widget->SetEnabled(1);
widget->InteractiveOff();
二、添加裁切包围盒
添加包围盒,包围盒就是模型的最小包围立方体,在包围盒每个面的中间有操作点,拖动操作点即可调整模型的裁切平面
核心代码:
m_box = vtkSmartPointer<View3D>::New();
m_box->SetInteractor(interactor);
m_box->SetRenderer(renderer);
m_box->SetPolyData(m_sourcepolydata);
m_box->SetActor(actor);
m_box->Start();
其中View3D是交互类,用于响应每次拖动控制点后的事件并将拖动的平面参数传给VtkBoxWidget类,VtkBoxWidget继承自vtk3DWidget,对其中的一些事件进行了重写,主要包围盒的显示和交互相关。部分核心代码如下:
#include "vtkCallbackCommand.h"
#include "vtkObject.h"
#include "vtkSmartPointer.h"
#include "vtkboxwidget.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkPolyData.h"
#include "vtkActor.h"
#include "vtkMapper.h"
class View3D :public vtkObject
{
public:
static View3D* New()
{
return new View3D();
}
View3D(void);
~View3D(void);
void Start();
//从主函数传参
void SetInteractor(vtkRenderWindowInteractor* interactor){m_Interactor = interactor;}
void SetRenderer(vtkSmartPointer<vtkRenderer> renderer){m_Renderer = renderer;}
void SetPolyData(vtkPolyData *p){m_polydata = p;}
void SetActor(vtkSmartPointer<vtkActor> actor){m_Actor = actor;}
void SetResourceColor(std::string name,double &r,double &g,double &b,double &opacity); //设置包围盒相关颜色
void OnBoxWidgetEndEvent();
static void ProcessEvent(vtkObject* p,unsigned long n,void* clientdata,void* calldata);//处理交互事件
vtkSmartPointer<VtkBoxWidget> m_BoxWidget; //包围盒类
vtkSmartPointer<vtkCallbackCommand> m_Callback;
vtkSmartPointer<vtkRenderer> m_Renderer;
vtkRenderWindowInteractor* m_Interactor;
vtkSmartPointer<vtkActor> m_Actor;
vtkPolyData * m_polydata;
};
三、显示效果
虽然不是真实裁切,但是视觉效果很好啦,再结合上一篇进行改进,也可以得到真实的切割数据
总结
该裁切方法主要在于交互的设计,所谓裁切工作其实是vtkMapper->SetClippingPlanes(vtkpalne*)方法完成的,关键在于正确传递vtkplane