您好,登錄后才能下訂單哦!
??VTK中體(vtkVolume)的裁剪可以通過體數據映射器(vtkVolumeMapper)設置裁剪平面(vtkPlane)進行裁剪(AddClippingPlane )。該裁剪平面可通過參數設置其屬性,也可使用平面窗口(vtkPlaneWidget)通過鼠標平移縮放旋轉至目標位置后,獲取該窗口包含的平面(GetPlane),并將其設置給提數據映射器(vtkVolumeMapper)進行裁剪。本文實現了通過鼠標操作平面窗口(vtkPlaneWidget)后進行體數據裁剪。
main.cpp
#include <QtWidgets/QApplication>
#include <QWidget>
#include <QPushButton>
#include <QGridLayout>
#include "CVtkPlaneCut.h"
int main( int argc, char *argv[] )
{
QApplication a( argc, argv );
QWidget* pWidget = new QWidget;
CVtkPlaneCut* pPlaneCut = new CVtkPlaneCut( pWidget );
QPushButton* pBtnClip = new QPushButton( "Clip" );
pBtnClip->setFixedHeight( 30 );
QObject::connect( pBtnClip, SIGNAL( clicked() ), pPlaneCut, SLOT( slotClipVolume() ) );
QVBoxLayout* pMainLayout = new QVBoxLayout;
pMainLayout->addWidget( pPlaneCut );
pMainLayout->addWidget( pBtnClip );
pWidget->setLayout( pMainLayout );
pWidget->show();
return a.exec();
}
CVtkPlaneCut .h
#ifndef CVTKPLANECUT_H
#define CVTKPLANECUT_H
#include "QVTKWidget.h"
#include "vtkSmartPointer.h"
class vtkVolume;
class vtkRenderWindow;
class vtkPlaneWidget;
class CVtkPlaneCut : public QVTKWidget
{
Q_OBJECT
public:
CVtkPlaneCut( QWidget *parent = 0 );
protected slots:
void slotClipVolume();
private:
vtkSmartPointer<vtkVolume> m_pVolume;
vtkSmartPointer<vtkRenderWindow> m_pRenderWindow;
vtkSmartPointer<vtkPlaneWidget> m_pPlaneWidget;
};
#endif // CVTKPLANECUT_H
CVtkPlaneCut .cpp
#include <vtkAutoInit.h>
VTK_MODULE_INIT( vtkRenderingOpenGL );
VTK_MODULE_INIT( vtkInteractionStyle );
#define vtkRenderingCore_AUTOINIT 4(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL,vtkRenderingOpenGL)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)
#include "CVtkPlaneCut.h"
#include <QFile>
#include "vtkImageData.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
#include "vtkPiecewiseFunction.h"
#include "vtkSmartVolumeMapper.h"
#include "vtkColorTransferFunction.h"
#include "vtkCamera.h"
#include "vtkPlane.h"
#include "vtkPlaneWidget.h"
#include "vtkImageShiftScale.h"
#include "vtkProperty.h"
CVtkPlaneCut::CVtkPlaneCut( QWidget *parent )
: QVTKWidget( parent )
{
/*Init RenderWindow*/
vtkSmartPointer<vtkRenderer> pRenderer = vtkSmartPointer<vtkRenderer>::New();
m_pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
m_pVolume = vtkSmartPointer<vtkVolume>::New();
m_pRenderWindow->AddRenderer( pRenderer );
this->SetRenderWindow( m_pRenderWindow );
/*Create Image Data*/
int nDims[ 3 ] = { 1 };
nDims[ 0 ] = 512;
nDims[ 1 ] = 512;
nDims[ 2 ] = 262;
double dSpacing[ 3 ] = { 0.1 };
dSpacing[ 0 ] = 0.78;
dSpacing[ 1 ] = 0.78;
dSpacing[ 2 ] = 3.27;
double dOrigin[ 3 ] = { 0.0 };
vtkSmartPointer<vtkImageData> pImageData = vtkSmartPointer<vtkImageData>::New();
pImageData->SetSpacing( dSpacing );
pImageData->SetDimensions( nDims );
pImageData->SetOrigin( dOrigin );
/*Read Data*/
QString strFilePath = "../TestData/CT_Body_512_512_262_0.78_0.78_3.27_2048_short.HU";
QFile file( strFilePath );
if( !file.open( QIODevice::ReadOnly ) )
return;
file.seek( 2048 );
int nSizeOfShot = sizeof( short );
long lLength = nDims[ 0 ] * nDims[ 1 ] * nDims[ 2 ];
char* pRawData = new char[ lLength * nSizeOfShot ];
long lRead = 0;
while( lRead < lLength * nSizeOfShot )
lRead += file.read( pRawData, lLength * nSizeOfShot );
pImageData->AllocateScalars( VTK_SHORT, 1 );
short* pScalarPointer = (short*)pImageData->GetScalarPointer();
short* pData = (short*)pRawData;
memcpy( pScalarPointer, pData, lLength );
file.close();
/* Volume Property */
//設置體繪制相關屬性
vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
volumeProperty->SetInterpolationTypeToLinear(); //設置線性插值方式
volumeProperty->ShadeOn();//開啟陰影屬性
volumeProperty->SetAmbient( 0.4 );//設置環境溫度
volumeProperty->SetDiffuse( 0.6 );//設置漫反射系數
volumeProperty->SetSpecular( 2 );//設置鏡面反射系數
//添加灰度不透明度屬性
vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
compositeOpacity->AddPoint( -15591, 0.0 );
compositeOpacity->AddPoint( 4876, 0.001 );
compositeOpacity->AddPoint( 7961, 1 );
compositeOpacity->AddPoint( 11110, 0.001 );
compositeOpacity->AddPoint( 32767, 0 );
volumeProperty->SetScalarOpacity(compositeOpacity);
//添加梯度不同明度屬性
vtkSmartPointer<vtkPiecewiseFunction> gradientOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
gradientOpacity->AddPoint( 0, 0.0 );
gradientOpacity->AddPoint( 200, 0.4 );
gradientOpacity->AddPoint( 500, 0.1 );
gradientOpacity->AddPoint( 800, 0.5 );
gradientOpacity->AddPoint( 1000, 0.6 );
volumeProperty->SetGradientOpacity(gradientOpacity);
//添加顏色傳輸
vtkSmartPointer<vtkColorTransferFunction> color = vtkSmartPointer<vtkColorTransferFunction>::New();
color->AddRGBPoint( 0, 0, 0, 0 );
color->AddRGBPoint( 200, 0.5, 0.3, 0 );
color->AddRGBPoint( 500, 0, 1.0, 0 );
color->AddRGBPoint( 600, 0, 0.5, 0.5 );
color->AddRGBPoint( 1000, 0.20, 0.5, 0.20 );
volumeProperty->SetColor( color );
/*Volume*/
vtkSmartPointer<vtkSmartVolumeMapper> volumeMapper = vtkSmartPointer<vtkSmartVolumeMapper>::New();
volumeMapper->SetInputData( pImageData );
m_pVolume->SetMapper( volumeMapper );
m_pVolume->SetProperty( volumeProperty );
m_pVolume->SetOrigin( m_pVolume->GetCenter() );
/*Render Window*/
pRenderer->AddVolume( m_pVolume );
pRenderer->ResetCamera();
m_pRenderWindow->Modified();
m_pRenderWindow->Render();
/*Clipping Plane Widget*/
m_pPlaneWidget = vtkSmartPointer<vtkPlaneWidget>::New();
m_pPlaneWidget->SetInteractor( m_pRenderWindow->GetInteractor() );//與交互器關聯
m_pPlaneWidget->SetInputData( pImageData );//設置數據集,用于初始化平面,可以不設置
m_pPlaneWidget->SetResolution( 50 );//即:設置網格數
m_pPlaneWidget->GetPlaneProperty()->SetColor( .2, .8, 0.1 );//設置顏色
m_pPlaneWidget->GetPlaneProperty()->SetOpacity( 0.5 );//設置透明度
m_pPlaneWidget->GetHandleProperty()->SetColor( 0, .4, .7 );//設置平面頂點顏色
m_pPlaneWidget->GetHandleProperty()->SetLineWidth( 1.5 );//設置平面線寬
m_pPlaneWidget->NormalToZAxisOn();//初始法線方向平行于Z軸
m_pPlaneWidget->SetRepresentationToWireframe();//平面顯示為網格屬性
m_pPlaneWidget->SetCenter( m_pVolume->GetCenter() );//設置平面坐標
m_pPlaneWidget->PlaceWidget();//放置平面
m_pPlaneWidget->On();//顯示平面
}
void CVtkPlaneCut::slotClipVolume()
{
//進行裁剪
vtkSmartPointer<vtkPlane> clippingPlane = vtkSmartPointer<vtkPlane>::New();
m_pPlaneWidget->GetPlane( clippingPlane );
m_pVolume->GetMapper()->AddClippingPlane( clippingPlane );
m_pVolume->Modified();
m_pRenderWindow->Modified();
m_pRenderWindow->Render();
}
初始界面
鼠標操作后界面
點擊"剪裁"按鈕后效果
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。