因为老师让我研究怎样在三维物体上切割任意平面,所以在网上查了查相关资料,基本上有两种方法,一种是用vtkPlaneWidget一种是用vtkImagePlaneWidget,这两种方法目前我都试了一下,总的来说vtkPlaneWidget更好交互一点,而vtkImagePlaneWidget的交互方式更复杂一点,且网上的代码在使用vtkImagePlaneWidget时,不能显示出切片图片,因此我对于网上的代码进行了修改。特在这里写下,供大家参考。
void main()
{
vtkSmartPointerpRender1 = vtkSmartPointer::New();
vtkSmartPointerpRender2 = vtkSmartPointer::New();
vtkSmartPointerpWin = vtkSmartPointer::New();
vtkSmartPointerpInt = vtkSmartPointer::New();
pWin->SetSize(600, 300);
pWin->AddRenderer(pRender1);
pWin->AddRenderer(pRender2);
pRender1->SetViewport(0, 0, .5, 1);
pRender2->SetViewport(0.5, 0, 1, 1);
pRender2->SetBackground(.3, .3, .3);
pInt->SetRenderWindow(pWin);
vtkSmartPointer<vtkDICOMImageReader>pReader = vtkSmartPointer<vtkDICOMImageReader>::New();
pReader->SetDirectoryName("C:\\Users\\song\\Desktop\\colonix-01");
pReader->SetDataByteOrderToLittleEndian();
pReader->Update();
double range[2];
pReader->GetOutput()->GetScalarRange(range);//得到标量范围
vtkSmartPointer<vtkImageShiftScale> m_pShift = vtkSmartPointer<vtkImageShiftScale>::New();//图像类型转换
m_pShift->SetShift(-1.0*range[0]);//设置偏移量
m_pShift->SetScale(255.0 / (range[1] - range[0]));//设置放缩值
m_pShift->SetOutputScalarTypeToUnsignedChar();
m_pShift->SetInputConnection(pReader->GetOutputPort());
m_pShift->ReleaseDataFlagOff();
m_pShift->Update();
vtkSmartPointer<vtkFixedPointVolumeRayCastMapper >pMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
pMapper->SetInputConnection(pReader->GetOutputPort()); //映射:第一步
vtkSmartPointer<vtkColorTransferFunction> pColor = vtkSmartPointer<vtkColorTransferFunction>::New(); //第二步:color
pColor->AddRGBSegment(0, 1, 1, 1, 255, 1, 1, 1);
vtkSmartPointer<vtkPiecewiseFunction> pPiceFun = vtkSmartPointer<vtkPiecewiseFunction>::New();
pPiceFun->AddSegment(0, 0, 3000, 1);//第三步: vtkPiecwise分段
pMapper->SetBlendModeToMaximumIntensity();
vtkSmartPointer<vtkVolumeProperty> pProperty = vtkSmartPointer<vtkVolumeProperty>::New();//设置属性
pProperty->SetColor(pColor);
pProperty->SetScalarOpacity(pPiceFun);
pProperty->SetInterpolationTypeToLinear();
pProperty->ShadeOff();
vtkSmartPointer<vtkVolume>pVolume = vtkSmartPointer<vtkVolume>::New();
pVolume->SetProperty(pProperty);
pVolume->SetMapper(pMapper); //生成体对象
pRender1->AddVolume(pVolume); //增加体数据到渲染器中渲染
vtkCellPicker * picker = vtkCellPicker::New();
picker->SetTolerance(0.005);
vtkSmartPointer<vtkImagePlaneWidget >pWidget = vtkSmartPointer<vtkImagePlaneWidget>::New();
pWidget->SetInteractor(pInt);
pWidget->SetPicker(picker);
pWidget->SetInputConnection(pReader->GetOutputPort());
//pWidget->SetResolution(10);//设置分辨率
pWidget->RestrictPlaneToVolumeOn();
pWidget->GetPlaneProperty()->SetColor(.9, .4, .4);
pWidget->TextureInterpolateOn();
pWidget->SetWindowLevel(1358, -27);
pWidget->SetDefaultRenderer(pRender1);
pWidget->DisplayTextOn();
pWidget->SetResliceInterpolateToLinear();
pWidget->SetPlaneOrientationToZAxes();
pWidget->SetSliceIndex(14);
pWidget->On();
pWidget->InteractionOn();
vtkSmartPointer<vtkPlaneSource>plane =
vtkSmartPointer<vtkPlaneSource>::New();
vtkSmartPointer<vtkPolyDataMapper>planeMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
planeMapper->SetInputConnection(plane->GetOutputPort());
vtkSmartPointer<vtkActor>planeActor =
vtkSmartPointer<vtkActor>::New();
planeActor->SetMapper(planeMapper);
planeActor->SetTexture(pWidget->GetTexture());
pRender2->AddActor(planeActor);
pWin->Render();
pInt->Initialize();
pInt->Start();
//camera->Delete();
}
运行结果
在这里我还有个疑问,就是这个Widget的交互方式有点麻烦,不知有谁能告诉我怎么改交互方式,使切面方便移动。