VTK交互之vtkVolumePicker

基本概念

vtkVolumePicker是vtkCellPicker的子类,增强的体数据光线投射拾取器。

示例演示

我们利用vtkVolumePicker对体数据进行拾取。

/**********************************************************************

Copyright (c) Mr.Bin. All rights reserved.
For more information visit: http://blog.csdn.net/webzhuce

**********************************************************************/
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageReader2.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkPiecewiseFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkMarchingCubes.h>
#include <vtkPolyDataNormals.h>
#include <vtkStripper.h>
#include <vtkCellLocator.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkLookupTable.h>
#include <vtkImageMapToColors.h>
#include <vtkImageActor.h>
#include <vtkImageMapper3D.h>
#include <vtkTransform.h>
#include <vtkPlane.h>
#include <vtkCamera.h>
#include <vtkConeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkVolumePicker.h>
#include <vtkCommand.h>

class vtkMyMouseCommand : public vtkCommand
{
public:
	static vtkMyMouseCommand *New()
	{
		return new vtkMyMouseCommand;
	}

	//A function to point an actor along a vector
	void PointCone(vtkActor *actor, double nx, double ny, double nz)
	{
		actor->SetOrientation(0.0, 0.0, 0.0);
		double n = std::sqrt(nx*nx + ny*ny + nz*nz);
		if (nx < 0.0)
		{
			actor->RotateWXYZ(180, 0, 1, 0);
			n = -n;

		}
		actor->RotateWXYZ(180, (nx + n)*0.5, ny*0.5, nz*0.5);
	}

	virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData)
	{
		//renWin->HideCursor();
		int x, y;
		iren->GetEventPosition(x, y);
		picker->Pick(x, y, 0, ren);
		double p[3];
		picker->GetPickPosition(p);
		std::cout << p[0]<< " "<< p[1]<<" " << p[2]<<std::endl;
		double n[3];
		picker->GetPickNormal(n);
		redCone->SetPosition(p[0], p[1], p[2]);
		PointCone(redCone, n[0], n[1], n[2]);
		greenCone->SetPosition(p[0], p[1], p[2]);
		PointCone(greenCone, -n[0], -n[1], -n[2]);
		iren->Render();
	}

	vtkRenderWindow *renWin;
	vtkRenderer *ren;
	vtkRenderWindowInteractor *iren;
	vtkVolumePicker *picker;
	vtkActor *redCone;
	vtkActor *greenCone;
};

int main(int, char *[])
{
	//renderer and interactor
	vtkNew<vtkRenderer> ren;
	vtkNew<vtkRenderWindow> renWin;
	renWin->AddRenderer(ren);
	vtkNew<vtkRenderWindowInteractor> iren;
	iren->SetRenderWindow(renWin);

	//read the volume
	vtkNew<vtkImageReader2> reader;
	reader->SetDataExtent(0, 63, 0, 63, 0, 92);
	reader->SetFileNameSliceOffset(1);
	reader->SetDataScalarTypeToUnsignedShort();
	reader->SetDataByteOrderToLittleEndian();
	reader->SetFilePrefix("H:/VTK/Build-VTK-8.2.0/ExternalData/Testing/Data/headsq/quarter");
	reader->SetDataSpacing(3.2, 3.2, 1.5);

	//set up the volume rendering
	vtkNew<vtkGPUVolumeRayCastMapper> volumeMapper;
	volumeMapper->SetInputConnection(reader->GetOutputPort());
	volumeMapper->CroppingOn();
	double croppingRegionPlanes[6] = {0.0, 141.6, 0.0, 201.6, 0.0, 138.0};
	volumeMapper->SetCroppingRegionPlanes(croppingRegionPlanes);

	vtkNew<vtkColorTransferFunction> volumeColor;
	volumeColor->AddRGBPoint(0, 0.0, 0.0, 0.0);
	volumeColor->AddRGBPoint(180, 0.3, 0.1, 0.2);
	volumeColor->AddRGBPoint(1000, 1.0, 0.7, 0.6);
	volumeColor->AddRGBPoint(2000, 1.0, 1.0, 0.9);

	vtkNew<vtkPiecewiseFunction> volumeScalarOpacity;
	volumeScalarOpacity->AddPoint(0, 0.0);
	volumeScalarOpacity->AddPoint(180, 0.0);
	volumeScalarOpacity->AddPoint(1000, 0.2);
	volumeScalarOpacity->AddPoint(2000, 0.8);

	vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
	volumeGradientOpacity->AddPoint(0, 0.0);
	volumeGradientOpacity->AddPoint(90, 0.5);
	volumeGradientOpacity->AddPoint(100, 1.0);

	vtkNew<vtkVolumeProperty> volumeProperty;
	volumeProperty->SetColor(volumeColor);
	volumeProperty->SetScalarOpacity(volumeScalarOpacity);
	volumeProperty->SetGradientOpacity(volumeGradientOpacity);
	volumeProperty->SetInterpolationTypeToLinear();
	volumeProperty->ShadeOff();
	volumeProperty->SetAmbient(0.6);
	volumeProperty->SetDiffuse(0.6);
	volumeProperty->SetSpecular(0.1);

	vtkNew<vtkVolume> volume;
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	// Do the surface rendering
	vtkNew<vtkMarchingCubes> boneExtractor;
	boneExtractor->SetInputConnection(reader->GetOutputPort());
	boneExtractor->SetValue(0, 1150);
	boneExtractor->Update();

	vtkNew<vtkPolyDataNormals>boneNormals;
	boneNormals->SetInputConnection(boneExtractor->GetOutputPort());
	boneNormals->SetFeatureAngle(60.0);

	vtkNew<vtkStripper> boneStripper;
	boneStripper->SetInputConnection(boneNormals->GetOutputPort());

	vtkNew<vtkCellLocator> boneLocator;
	boneLocator->SetDataSet(boneExtractor->GetOutput());
	boneLocator->LazyEvaluationOn();

	vtkNew<vtkPolyDataMapper> boneMapper;
	boneMapper->SetInputConnection(boneStripper->GetOutputPort());
	boneMapper->ScalarVisibilityOff();

	vtkNew<vtkProperty> boneProperty;
	boneProperty->SetColor(1.0, 1.0, 0.9);

	vtkNew<vtkActor> bone;
	bone->SetMapper(boneMapper);
	bone->SetProperty(boneProperty);

	//Create an image actor
	vtkNew<vtkLookupTable> table;
	table->SetRange(0, 2000);
	table->SetRampToLinear();
	table->SetValueRange(0, 1);
	table->SetHueRange(0, 0);
	table->SetSaturationRange(0, 0);

	vtkNew<vtkImageMapToColors> mapToColors;
	mapToColors->SetInputConnection(reader->GetOutputPort());
	mapToColors->SetLookupTable(table);
	mapToColors->Update();

	vtkNew<vtkImageActor> imageActor;
	imageActor->GetMapper()->SetInputConnection(mapToColors->GetOutputPort());
	imageActor->SetDisplayExtent(32, 32, 0, 63, 0, 92);

	//make a transform and some clipping planes
	vtkNew<vtkTransform> transform;
	transform->RotateWXYZ(-20, 0.0, -0.7, 0.7);
	volume->SetUserTransform(transform);
	bone->SetUserTransform(transform);
	imageActor->SetUserTransform(transform);

	auto c = volume->GetCenter();

	vtkNew<vtkPlane> volumeClip;
	volumeClip->SetNormal(0, 1, 0);
	volumeClip->SetOrigin(c[0], c[1], c[2]);

	vtkNew<vtkPlane> boneClip;
	boneClip->SetNormal(1, 0, 0);
	boneClip->SetOrigin(c[0], c[1], c[2]);

	volumeMapper->AddClippingPlane(volumeClip);
	boneMapper->AddClippingPlane(boneClip);

	ren->AddViewProp(volume);
	ren->AddViewProp(bone);
	ren->AddViewProp(imageActor);

	auto camera = ren->GetActiveCamera();
	camera->SetFocalPoint(c[0], c[1], c[2]);
	camera->SetPosition(c[0] + 500, c[1] - 100, c[2] - 100);
	camera->SetViewUp(0, 0, -1);

	//the cone points along the - x axis
	vtkNew<vtkConeSource> coneSource;
	coneSource->CappingOn();
	coneSource->SetHeight(12);
	coneSource->SetRadius(5);
	coneSource->SetResolution(31);
	coneSource->SetCenter(6, 0, 0);
	coneSource->SetDirection(-1, 0, 0);

	vtkNew<vtkDataSetMapper> coneMapper;
	coneMapper->SetInputConnection(coneSource->GetOutputPort());

	vtkNew<vtkActor> redCone;
	redCone->PickableOff();
	redCone->SetMapper(coneMapper);
	redCone->GetProperty()->SetColor(1, 0, 0);

	vtkNew<vtkActor> greenCone;
	greenCone->PickableOff();
	greenCone->SetMapper(coneMapper);
	greenCone->GetProperty()->SetColor(0, 1, 0);

	//Add the two cones(or just one, if you want);
	ren->AddViewProp(redCone);
	ren->AddViewProp(greenCone);

	//the picker
	vtkNew<vtkVolumePicker> picker ;
	picker->SetTolerance(1e-6);
	picker->SetVolumeOpacityIsovalue(0.1);
	//locator is optional, but improves performance for large polydata
	picker->AddLocator(boneLocator);
	
	renWin->Render();
	vtkNew<vtkMyMouseCommand> mouseCommand;
	mouseCommand->renWin = renWin;
	mouseCommand->ren= ren;
	mouseCommand->iren = iren;
	mouseCommand->picker = picker;
	mouseCommand->redCone = redCone;
	mouseCommand->greenCone = greenCone;
	iren->AddObserver(vtkCommand::MouseMoveEvent, mouseCommand);
	iren->Start();
	return EXIT_SUCCESS;
}

运行结果

红锥体和绿锥体尖头相交处即拾取位置
在这里插入图片描述

参考资料

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值