本篇文章将参考大神们的足迹,模仿这实现四视图。
电梯
1 参考资料
2 参考代码
3 自己的代码
4 运行效果
☞ 源码
1 参考资料
其实说四视图是不是很不专业,是不是应该叫多平面重建及三维切片显示呀。参考资料如下:
参考:https://blog.csdn.net/hit1524468/article/details/113446783
https://www.cnblogs.com/fuzhuoxin/p/12513872.html
https://blog.csdn.net/weixin_38500110/article/details/78807196
2 参考代码
#ifndef QtVTKRenderWindows_H #define QtVTKRenderWindows_H #include "vtkSmartPointer.h" #include "vtkResliceImageViewer.h" #include "vtkImagePlaneWidget.h" #include "vtkDistanceWidget.h" #include "vtkResliceImageViewerMeasurements.h" #include <QMainWindow> #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2) VTK_MODULE_INIT(vtkInteractionStyle) VTK_MODULE_INIT(vtkRenderingFreeType) // Forward Qt class declarations class Ui_QtVTKRenderWindows; class QtVTKRenderWindows : public QMainWindow { Q_OBJECT public: // Constructor/Destructor QtVTKRenderWindows(int argc, char *argv[]); ~QtVTKRenderWindows() override {} public slots: virtual void slotExit(); virtual void resliceMode(int); virtual void thickMode(int); virtual void SetBlendModeToMaxIP(); virtual void SetBlendModeToMinIP(); virtual void SetBlendModeToMeanIP(); virtual void SetBlendMode(int); virtual void ResetViews(); virtual void Render(); virtual void AddDistanceMeasurementToView1(); virtual void AddDistanceMeasurementToView( int ); protected: vtkSmartPointer< vtkResliceImageViewer > riw[3]; vtkSmartPointer< vtkImagePlaneWidget > planeWidget[3]; vtkSmartPointer< vtkDistanceWidget > DistanceWidget[3]; vtkSmartPointer< vtkResliceImageViewerMeasurements > ResliceMeasurements; protected slots: private: // Designer form Ui_QtVTKRenderWindows *ui; }; #endif // QtVTKRenderWindows_H
#include "ui_QtVTKRenderWindows.h" #include "QtVTKRenderWindows.h" #include "vtkBoundedPlanePointPlacer.h" #include "vtkCellPicker.h" #include "vtkCommand.h" #include "vtkDICOMImageReader.h" #include "vtkDistanceRepresentation.h" #include "vtkDistanceRepresentation2D.h" #include "vtkDistanceWidget.h" #include <vtkGenericOpenGLRenderWindow.h> #include "vtkHandleRepresentation.h" #include "vtkImageData.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageSlabReslice.h" #include "vtkInteractorStyleImage.h" #include "vtkLookupTable.h" #include "vtkPlane.h" #include "vtkPlaneSource.h" #include "vtkPointHandleRepresentation2D.h" #include "vtkPointHandleRepresentation3D.h" #include "vtkProperty.h" #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include "vtkRenderWindowInteractor.h" #include "vtkResliceImageViewer.h" #include "vtkResliceCursorLineRepresentation.h" #include "vtkResliceCursorThickLineRepresentation.h" #include "vtkResliceCursorWidget.h" #include "vtkResliceCursorActor.h" #include "vtkResliceCursorPolyDataAlgorithm.h" #include "vtkResliceCursor.h" #include "vtkMetaImageReader.h" #include "vtkResliceImageViewerMeasurements.h" //---------------------------------------------------------------------------- class vtkResliceCursorCallback : public vtkCommand { public: static vtkResliceCursorCallback *New() { return new vtkResliceCursorCallback; } void Execute( vtkObject *caller, unsigned long ev, void *callData ) override { if (ev == vtkResliceCursorWidget::WindowLevelEvent || ev == vtkCommand::WindowLevelEvent || ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent) { // Render everything for (int i = 0; i < 3; i++) { this->RCW[i]->Render(); } this->IPW[0]->GetInteractor()->GetRenderWindow()->Render(); return; } vtkImagePlaneWidget* ipw = dynamic_cast< vtkImagePlaneWidget* >( caller ); if (ipw) { double* wl = static_cast<double*>( callData ); if ( ipw == this->IPW[0] ) { this->IPW[1]->SetWindowLevel(wl[0],wl[1],1); this->IPW[2]->SetWindowLevel(wl[0],wl[1],1); } else if( ipw == this->IPW[1] ) { this->IPW[0]->SetWindowLevel(wl[0],wl[1],1); this->IPW[2]->SetWindowLevel(wl[0],wl[1],1); } else if (ipw == this->IPW[2]) { this->IPW[0]->SetWindowLevel(wl[0],wl[1],1); this->IPW[1]->SetWindowLevel(wl[0],wl[1],1); } } vtkResliceCursorWidget *rcw = dynamic_cast< vtkResliceCursorWidget * >(caller); if (rcw) { vtkResliceCursorLineRepresentation *rep = dynamic_cast< vtkResliceCursorLineRepresentation * >(rcw->GetRepresentation()); // Although the return value is not used, we keep the get calls // in case they had side-effects rep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor(); for (int i = 0; i < 3; i++) { vtkPlaneSource *ps = static_cast< vtkPlaneSource * >( this->IPW[i]->GetPolyDataAlgorithm()); ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()-> GetPlaneSource()->GetOrigin()); ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()-> GetPlaneSource()->GetPoint1()); ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()-> GetPlaneSource()->GetPoint2()); // If the reslice plane has modified, update it on the 3D widget this->IPW[i]->UpdatePlacement(); } } // Render everything for (int i = 0; i < 3; i++) { this->RCW[i]->Render(); } this->IPW[0]->GetInteractor()->GetRenderWindow()->Render(); } vtkResliceCursorCallback() {} vtkImagePlaneWidget* IPW[3]; vtkResliceCursorWidget *RCW[3]; }; QtVTKRenderWindows::QtVTKRenderWindows( int vtkNotUsed(argc), char *argv[]) { this->ui = new Ui_QtVTKRenderWindows; this->ui->setupUi(this); #if 0 vtkSmartPointer< vtkDICOMImageReader > reader = vtkSmartPointer<vtkDICOMImageReader >::New(); // reader->SetDirectoryName(argv[1]); reader->SetDirectoryName("/home/hsw/Qt_workSpace/build-RSVtkLearn_FourPaneViewer-Desktop_Qt_5_12_2_GCC_64bit-Debug/DCM/"); #else vtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New(); reader->SetFileName("/home/hsw/Downloads/brain/brain.mhd"); #endif reader->Update(); int imageDims[3]; reader->GetOutput()->GetDimensions(imageDims); for (int i = 0; i < 3; i++) { riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New(); vtkNew<vtkGenericOpenGLRenderWindow> renderWindow; riw[i]->SetRenderWindow(renderWindow); } this->ui->view1->SetRenderWindow(riw[0]->GetRenderWindow()); riw[0]->SetupInteractor(this->ui->view1->GetRenderWindow()->GetInteractor()); this->ui->view2->SetRenderWindow(riw[1]->GetRenderWindow()); riw[1]->SetupInteractor(this->ui->view2->GetRenderWindow()->GetInteractor()); this->ui->view3->SetRenderWindow(riw[2]->GetRenderWindow()); riw[2]->SetupInteractor(this->ui->view3->GetRenderWindow()->GetInteractor()); for (int i = 0; i < 3; i++) { // make them all share the same reslice cursor object. vtkResliceCursorLineRepresentation *rep = vtkResliceCursorLineRepresentation::SafeDownCast(riw[i]->GetResliceCursorWidget()->GetRepresentation()); riw[i]->SetResliceCursor(riw[0]->GetResliceCursor()); rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i); riw[i]->SetInputData(reader->GetOutput()); riw[i]->SetSliceOrientation(i); riw[i]->SetResliceModeToAxisAligned(); } vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New(); picker->SetTolerance(0.005); vtkSmartPointer<vtkProperty> ipwProp = vtkSmartPointer<vtkProperty>::New(); vtkSmartPointer< vtkRenderer > ren = vtkSmartPointer< vtkRenderer >::New(); vtkNew<vtkGenericOpenGLRenderWindow> renderWindow; this->ui->view4->SetRenderWindow(renderWindow); this->ui->view4->GetRenderWindow()->AddRenderer(ren); vtkRenderWindowInteractor *iren = this->ui->view4->GetInteractor(); for (int i = 0; i < 3; i++) { planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New(); planeWidget[i]->SetInteractor( iren ); planeWidget[i]->SetPicker(picker); planeWidget[i]->RestrictPlaneToVolumeOn(); double color[3] = {0, 0, 0}; color[i] = 1; planeWidget[i]->GetPlaneProperty()->SetColor(color); color[0] /= 4.0; color[1] /= 4.0; color[2] /= 4.0; riw[i]->GetRenderer()->SetBackground( color ); planeWidget[i]->SetTexturePlaneProperty(ipwProp); planeWidget[i]->TextureInterpolateOff(); planeWidget[i]->SetResliceInterpolateToLinear(); planeWidget[i]->SetInputConnection(reader->GetOutputPort()); planeWidget[i]->SetPlaneOrientation(i); planeWidget[i]->SetSliceIndex(imageDims[i]/2); planeWidget[i]->DisplayTextOn(); planeWidget[i]->SetDefaultRenderer(ren); planeWidget[i]->SetWindowLevel(1358, -27); planeWidget[i]->On(); planeWidget[i]->InteractionOn(); } vtkSmartPointer<vtkResliceCursorCallback> cbk = vtkSmartPointer<vtkResliceCursorCallback>::New(); for (int i = 0; i < 3; i++) { cbk->IPW[i] = planeWidget[i]; cbk->RCW[i] = riw[i]->GetResliceCursorWidget(); riw[i]->GetResliceCursorWidget()->AddObserver( vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver( vtkResliceCursorWidget::WindowLevelEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver( vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver( vtkResliceCursorWidget::ResetCursorEvent, cbk ); riw[i]->GetInteractorStyle()->AddObserver( vtkCommand::WindowLevelEvent, cbk ); // Make them all share the same color map. riw[i]->SetLookupTable(riw[0]->GetLookupTable()); planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable()); //planeWidget[i]->GetColorMap()->SetInput(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput()); planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()); } this->ui->view1->show(); this->ui->view2->show(); this->ui->view3->show(); // Set up action signals and slots connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit())); connect(this->ui->resliceModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(resliceMode(int))); connect(this->ui->thickModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(thickMode(int))); this->ui->thickModeCheckBox->setEnabled(0); connect(this->ui->radioButton_Max, SIGNAL(pressed()), this, SLOT(SetBlendModeToMaxIP())); connect(this->ui->radioButton_Min, SIGNAL(pressed()), this, SLOT(SetBlendModeToMinIP())); connect(this->ui->radioButton_Mean, SIGNAL(pressed()), this, SLOT(SetBlendModeToMeanIP())); this->ui->blendModeGroupBox->setEnabled(0); connect(this->ui->resetButton, SIGNAL(pressed()), this, SLOT(ResetViews())); connect(this->ui->AddDistance1Button, SIGNAL(pressed()), this, SLOT(AddDistanceMeasurementToView1())); }; void QtVTKRenderWindows::slotExit() { qApp->exit(); } void QtVTKRenderWindows::resliceMode(int mode) { this->ui->thickModeCheckBox->setEnabled(mode ? 1 : 0); this->ui->blendModeGroupBox->setEnabled(mode ? 1 : 0); for (int i = 0; i < 3; i++) { riw[i]->SetResliceMode(mode ? 1 : 0); riw[i]->GetRenderer()->ResetCamera(); riw[i]->Render(); } } void QtVTKRenderWindows::thickMode(int mode) { for (int i = 0; i < 3; i++) { riw[i]->SetThickMode(mode ? 1 : 0); riw[i]->Render(); } } void QtVTKRenderWindows::SetBlendMode(int m) { for (int i = 0; i < 3; i++) { vtkImageSlabReslice *thickSlabReslice = vtkImageSlabReslice::SafeDownCast( vtkResliceCursorThickLineRepresentation::SafeDownCast( riw[i]->GetResliceCursorWidget()->GetRepresentation())->GetReslice()); thickSlabReslice->SetBlendMode(m); riw[i]->Render(); } } void QtVTKRenderWindows::SetBlendModeToMaxIP() { this->SetBlendMode(VTK_IMAGE_SLAB_MAX); } void QtVTKRenderWindows::SetBlendModeToMinIP() { this->SetBlendMode(VTK_IMAGE_SLAB_MIN); } void QtVTKRenderWindows::SetBlendModeToMeanIP() { this->SetBlendMode(VTK_IMAGE_SLAB_MEAN); } void QtVTKRenderWindows::ResetViews() { // Reset the reslice image views for (int i = 0; i < 3; i++) { riw[i]->Reset(); } // Also sync the Image plane widget on the 3D top right view with any // changes to the reslice cursor. for (int i = 0; i < 3; i++) { vtkPlaneSource *ps = static_cast< vtkPlaneSource * >( planeWidget[i]->GetPolyDataAlgorithm()); ps->SetNormal(riw[0]->GetResliceCursor()->GetPlane(i)->GetNormal()); ps->SetCenter(riw[0]->GetResliceCursor()->GetPlane(i)->GetOrigin()); // If the reslice plane has modified, update it on the 3D widget this->planeWidget[i]->UpdatePlacement(); } // Render in response to changes. this->Render(); } void QtVTKRenderWindows::Render() { for (int i = 0; i < 3; i++) { riw[i]->Render(); } this->ui->view3->GetRenderWindow()->Render(); } void QtVTKRenderWindows::AddDistanceMeasurementToView1() { this->AddDistanceMeasurementToView(1); } void QtVTKRenderWindows::AddDistanceMeasurementToView(int i) { // remove existing widgets. if (this->DistanceWidget[i]) { this->DistanceWidget[i]->SetEnabled(0); this->DistanceWidget[i] = nullptr; } // add new widget this->DistanceWidget[i] = vtkSmartPointer< vtkDistanceWidget >::New(); this->DistanceWidget[i]->SetInteractor( this->riw[i]->GetResliceCursorWidget()->GetInteractor()); // Set a priority higher than our reslice cursor widget this->DistanceWidget[i]->SetPriority( this->riw[i]->GetResliceCursorWidget()->GetPriority() + 0.01); vtkSmartPointer< vtkPointHandleRepresentation2D > handleRep = vtkSmartPointer< vtkPointHandleRepresentation2D >::New(); vtkSmartPointer< vtkDistanceRepresentation2D > distanceRep = vtkSmartPointer< vtkDistanceRepresentation2D >::New(); distanceRep->SetHandleRepresentation(handleRep); this->DistanceWidget[i]->SetRepresentation(distanceRep); distanceRep->InstantiateHandleRepresentation(); distanceRep->GetPoint1Representation()->SetPointPlacer(riw[i]->GetPointPlacer()); distanceRep->GetPoint2Representation()->SetPointPlacer(riw[i]->GetPointPlacer()); // Add the distance to the list of widgets whose visibility is managed based // on the reslice plane by the ResliceImageViewerMeasurements class this->riw[i]->GetMeasurements()->AddItem(this->DistanceWidget[i]); this->DistanceWidget[i]->CreateDefaultRepresentation(); this->DistanceWidget[i]->EnabledOn(); }
3 自己的代码
#ifndef IMAGEMANAGE_H #define IMAGEMANAGE_H #include <QWidget> #include <QSplitter> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGridLayout> #include <QResizeEvent> #include <QtDebug> #include "QVTKOpenGLWidget.h" //新版本,旧版QVTKWidget #include "vtkAutoInit.h" #include "vtkSmartPointer.h" #include "vtkResliceImageViewer.h" #include "vtkImagePlaneWidget.h" #include "vtkDistanceWidget.h" #include "vtkResliceImageViewerMeasurements.h" #include "vtkBoundedPlanePointPlacer.h" #include "vtkCellPicker.h" #include "vtkCommand.h" #include "vtkDICOMImageReader.h" #include "vtkDistanceRepresentation.h" #include "vtkDistanceRepresentation2D.h" #include "vtkDistanceWidget.h" #include <vtkGenericOpenGLRenderWindow.h> #include "vtkHandleRepresentation.h" #include "vtkImageData.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageSlabReslice.h" #include "vtkInteractorStyleImage.h" #include "vtkLookupTable.h" #include "vtkPlane.h" #include "vtkPlaneSource.h" #include "vtkPointHandleRepresentation2D.h" #include "vtkPointHandleRepresentation3D.h" #include "vtkProperty.h" #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include "vtkRenderWindowInteractor.h" #include "vtkResliceImageViewer.h" #include "vtkResliceCursorLineRepresentation.h" #include "vtkResliceCursorThickLineRepresentation.h" #include "vtkResliceCursorWidget.h" #include "vtkResliceCursorActor.h" #include "vtkResliceCursorPolyDataAlgorithm.h" #include "vtkResliceCursor.h" #include "vtkResliceImageViewerMeasurements.h" class vtkResliceCursorCallback; namespace Ui { class ImageManage; } class ImageManage : public QWidget { Q_OBJECT public: explicit ImageManage(QWidget *parent = nullptr); ~ImageManage(); void setCurrentTab(int temp =0); public slots: /** * @brief slot_ReaderDICOMImage * @param fn * 读取DICOM文件 */ void slot_ReaderDICOMImage(const char* fn); protected: void resizeEvent(QResizeEvent *event) override; private: Ui::ImageManage *ui; QSplitter *mSplitterMain = nullptr; QSplitter *mSplitterVertical = nullptr; QSplitter *mSplitterUp = nullptr; QSplitter *mSplitterDown = nullptr; double color[3] = {0,0,0}; //颜色 vtkSmartPointer<vtkDICOMImageReader> reader = nullptr; //读取DICOM文件 int imageDims[3] = {0}; //暂时不理解 vtkSmartPointer< vtkResliceImageViewer > riw[3]; //三个二维视图 vtkSmartPointer< vtkImagePlaneWidget > planeWidget[3]; vtkSmartPointer< vtkDistanceWidget > DistanceWidget[3]; //测试距离的,暂时没有移植,无用 vtkSmartPointer< vtkResliceImageViewerMeasurements > ResliceMeasurements; //不知道干啥,没有用到 vtkSmartPointer<vtkProperty> ipwProp; //属性 vtkSmartPointer<vtkCellPicker> picker; //拾取器 vtkSmartPointer< vtkRenderer > ren; //3D渲染器 vtkSmartPointer<vtkResliceCursorCallback> cbk; //回调类 }; #endif // IMAGEMANAGE_H
#include "imagemanage.h" #include "ui_imagemanage.h" class vtkResliceCursorCallback : public vtkCommand { public: static vtkResliceCursorCallback *New() { return new vtkResliceCursorCallback; } void Execute( vtkObject *caller, unsigned long ev, void *callData ) override { if (ev == vtkResliceCursorWidget::WindowLevelEvent || ev == vtkCommand::WindowLevelEvent || ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent) { // Render everything for (int i = 0; i < 3; i++) { this->RCW[i]->Render(); } this->IPW[0]->GetInteractor()->GetRenderWindow()->Render(); // return; //这里需要注释掉,不然呵呵呵,返回了,还搞个毛线 } vtkImagePlaneWidget* ipw = dynamic_cast< vtkImagePlaneWidget* >( caller ); // qDebug() << "11" << caller << ipw; if (ipw) { double* wl = static_cast<double*>( callData ); if ( ipw == this->IPW[0] ) { this->IPW[1]->SetWindowLevel(wl[0],wl[1],1); this->IPW[2]->SetWindowLevel(wl[0],wl[1],1); } else if( ipw == this->IPW[1] ) { this->IPW[0]->SetWindowLevel(wl[0],wl[1],1); this->IPW[2]->SetWindowLevel(wl[0],wl[1],1); } else if (ipw == this->IPW[2]) { this->IPW[0]->SetWindowLevel(wl[0],wl[1],1); this->IPW[1]->SetWindowLevel(wl[0],wl[1],1); } } vtkResliceCursorWidget *rcw = dynamic_cast<vtkResliceCursorWidget * >(caller); // qDebug() << "22" << caller << rcw; if (rcw) { vtkResliceCursorLineRepresentation *rep = dynamic_cast< vtkResliceCursorLineRepresentation * >(rcw->GetRepresentation()); // Although the return value is not used, we keep the get calls // in case they had side-effects rep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor(); for (int i = 0; i < 3; i++) { vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(this->IPW[i]->GetPolyDataAlgorithm()); ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetOrigin()); ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()-> GetPlaneSource()->GetPoint1()); ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetPoint2()); // If the reslice plane has modified, update it on the 3D widget this->IPW[i]->UpdatePlacement(); } } // Render everything for (int i = 0; i < 3; i++) { this->RCW[i]->Render(); } this->IPW[0]->GetInteractor()->GetRenderWindow()->Render(); } vtkResliceCursorCallback() {} vtkImagePlaneWidget* IPW[3]; vtkResliceCursorWidget *RCW[3]; }; static QPoint lastPos; ImageManage::ImageManage(QWidget *parent) :QWidget(parent),ui(new Ui::ImageManage) { ui->setupUi(this); /******************窗口大小分割*************************/ mSplitterMain = new QSplitter(Qt::Horizontal,this); mSplitterVertical = new QSplitter(Qt::Vertical,mSplitterMain); mSplitterUp = new QSplitter(Qt::Horizontal,mSplitterVertical); mSplitterUp->addWidget(ui->widget_1); mSplitterUp->addWidget(ui->widget_2); mSplitterUp->setStretchFactor(0,1); mSplitterUp->setStretchFactor(1,1); mSplitterDown = new QSplitter(Qt::Horizontal,mSplitterVertical); mSplitterDown->addWidget(ui->widget_3); mSplitterDown->addWidget(ui->widget_4); mSplitterDown->setStretchFactor(0,1); mSplitterDown->setStretchFactor(1,1); mSplitterMain->insertWidget(0,mSplitterVertical); mSplitterMain->insertWidget(1,ui->widget_5); mSplitterMain->setStretchFactor(0,1); //很魔性啊 } ImageManage::~ImageManage() { delete ui; } void ImageManage::setCurrentTab(int temp) { Q_UNUSED(temp); } void ImageManage::slot_ReaderDICOMImage(const char *fn) { if(!reader) { reader = vtkSmartPointer<vtkDICOMImageReader>::New(); } reader->SetDirectoryName(fn); //这里主要,是文件夹哈,不是文件名 reader->Update(); //得更新呀,惰性渲染 reader->GetOutput()->GetDimensions(imageDims); //还不理解,翻译为获取维度,注释掉以后三维中有影响 for (auto i = 0; i < 3; i++) { riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New(); vtkNew<vtkGenericOpenGLRenderWindow> renderWindow; riw[i]->SetRenderWindow(renderWindow); } // ui->widget_1->SetRenderWindow(riw[0]->GetRenderWindow()); riw[0]->SetupInteractor(ui->widget_1->GetRenderWindow()->GetInteractor()); riw[0]->SetRenderWindow(ui->widget_1->GetRenderWindow()); // ui->widget_2->SetRenderWindow(riw[1]->GetRenderWindow()); riw[1]->SetupInteractor(ui->widget_2->GetRenderWindow()->GetInteractor()); riw[1]->SetRenderWindow(ui->widget_2->GetRenderWindow()); // ui->widget_3->SetRenderWindow(riw[2]->GetRenderWindow()); riw[2]->SetRenderWindow(ui->widget_3->GetRenderWindow()); riw[2]->SetupInteractor(ui->widget_3->GetRenderWindow()->GetInteractor()); for (int i = 0; i < 3; i++) { // make them all share the same reslice cursor object. vtkResliceCursorLineRepresentation *rep =vtkResliceCursorLineRepresentation::SafeDownCast(riw[i]->GetResliceCursorWidget()->GetRepresentation()); riw[i]->SetResliceCursor(riw[0]->GetResliceCursor()); rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i); riw[i]->SetInputData(reader->GetOutput()); riw[i]->SetSliceOrientation(i); riw[i]->SetResliceModeToAxisAligned(); } picker = vtkSmartPointer<vtkCellPicker>::New(); picker->SetTolerance(0.005); ipwProp = vtkSmartPointer<vtkProperty>::New(); ren = vtkSmartPointer< vtkRenderer >::New(); ui->widget_4->GetRenderWindow()->AddRenderer(ren); for (int i = 0; i < 3; i++) { planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New(); planeWidget[i]->SetInteractor( ui->widget_4->GetInteractor() ); planeWidget[i]->SetPicker(picker); planeWidget[i]->RestrictPlaneToVolumeOn(); color[0] = 0; color[1] = 0; color[2] = 0; color[i] = 1; planeWidget[i]->GetPlaneProperty()->SetColor(color); color[0] = 0; color[1] = 0; color[2] = 0; riw[i]->GetRenderer()->SetBackground( color ); planeWidget[i]->SetTexturePlaneProperty(ipwProp); planeWidget[i]->TextureInterpolateOff(); planeWidget[i]->SetResliceInterpolateToLinear(); planeWidget[i]->SetInputConnection(reader->GetOutputPort()); planeWidget[i]->SetPlaneOrientation(i); planeWidget[i]->SetSliceIndex(imageDims[i]/2); planeWidget[i]->DisplayTextOn(); planeWidget[i]->SetDefaultRenderer(ren); planeWidget[i]->SetWindowLevel(1358, -27); planeWidget[i]->On(); planeWidget[i]->InteractionOn(); } cbk = vtkSmartPointer<vtkResliceCursorCallback>::New(); for (int i = 0; i < 3; i++) { cbk->IPW[i] = planeWidget[i]; cbk->RCW[i] = riw[i]->GetResliceCursorWidget(); riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::WindowLevelEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk ); riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResetCursorEvent, cbk ); riw[i]->GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, cbk ); // Make them all share the same color map. riw[i]->SetLookupTable(riw[0]->GetLookupTable()); planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable()); //planeWidget[i]->GetColorMap()->SetInput(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput()); planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()); } // ui->widget_1->GetRenderWindow()->Render(); // ui->widget_2->GetRenderWindow()->Render(); // ui->widget_3->GetRenderWindow()->Render(); // ui->widget_4->GetRenderWindow()->Render(); //十字线 for (int i = 0; i < 3; i++) { riw[i]->SetResliceMode(1); riw[i]->GetRenderer()->ResetCamera(); riw[i]->Render(); } // 还不知道干啥 // for (int i = 0; i < 3; i++) // { // riw[i]->SetThickMode(1); // riw[i]->Render(); // } // for (int i = 0; i < 3; i++) // { // vtkImageSlabReslice *thickSlabReslice = vtkImageSlabReslice::SafeDownCast( // vtkResliceCursorThickLineRepresentation::SafeDownCast( // riw[i]->GetResliceCursorWidget()->GetRepresentation())->GetReslice()); // thickSlabReslice->SetBlendMode(1); // riw[i]->Render(); // } } void ImageManage::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); mSplitterMain->resize(this->size()); }