VTK+Qt使用BoxWidget包围盒对三维模型进行手动交互切割

VTK+Qt三维可视化系列应用

第二篇 使用BoxWidget包围盒模拟平面切割


文章目录

  • VTK+Qt三维可视化系列应用
  • 前言
  • 一、载入模型
  • 二、添加裁切包围盒
  • 三、显示效果
  • 总结


前言

对STL模型的包围盒进行交互从而对模型的“切割”,加引号是因为其实只是设置了类似于摄像机的裁切平面,使视觉上只能看见包围盒内的一部分物体


一、载入模型

导入自定义的STL模型,是用3DBuilder随便画的,便于观察效果
VTK+Qt使用BoxWidget包围盒对三维模型进行手动交互切割_第1张图片
主要代码:

    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

你可能感兴趣的:(VTK,C++,vtk,qt,c++,图形学)