[vtkusers] Need help on vtkImageReslice, Why I can not get the image of Sagittal and coronal plane?

John Drescher drescherjm at gmail.com
Sat Apr 18 07:26:05 EDT 2009


On Sat, Apr 18, 2009 at 3:54 AM, Jérôme <jerome.velut at gmail.com> wrote:
> Hi Liang,
>
> I am not aware of the ITK example, but I am quite sure it uses the
> vtkImagePlaneWidget. It does what you want, with interaction on the plane
> added (you can move through the volume).
>
> Jerome
>

Not directly, the text vtkImagePlaneWidget does not appear in any file
in my project.

Attached is the file that I use to view the Coronal, Axial, and Saggital
views of my Lung CT cases.

John
-------------- next part --------------
#include "ImageSliceViewer.h"

#include "vtkImageData.h"
#include "vtkInteractorStyleImage.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"

#include "InteractorObserver.h"

#include "itkPoint.h"

#include "ClickedPointEvent.h"
#include "vtkCoordinate.h"

#include "vtkCamera.h"
#include "vtkRenderer.h"
#include "vtkImageActor.h"
#include "vtkRenderWindow.h"
#include "vtkCommand.h"
#include "vtkInteractorStyleImage.h"
#include "vtkSphereSource.h" 
#include "vtkPolyDataMapper.h" 
#include "laVTKSinkFilter.h"
#include "vtkDataObject.h"

#ifndef vtkFloatingPointType
# define vtkFloatingPointType vtkFloatingPointType
typedef float vtkFloatingPointType;
#endif

namespace ISIS
{

/////////////////////////////////////////////////////////////////////////////////////////

	class ImageSliceViewer::isisPrivate
	{
	public:
		isisPrivate();
	public:
		typedef laVTKSinkFilter<quint8,3> InputImageFilterType;
	public:
		vtkImageActor     * m_Actor;

		vtkRenderer       * m_Renderer;

		vtkCamera         * m_Camera;

		vtkRenderWindow   * m_RenderWindow;

		SliceOrientationType     m_Orientation;

		int                 m_SliceNum;

		vtkCommand        * m_InteractorObserver;

		itk::Object::Pointer   m_Notifier;

		double              m_NearPlane;

		double              m_FarPlane;

		double              m_ZoomFactor;

		double               m_SelectPoint[3];

#ifdef NEED_SPHERE_ACTOR
		vtkActor          * m_SphereActor;

		vtkSphereSource   * m_Sphere;

#endif //def NEED_SPHERE_ACTOR

		InputImageFilterType*		m_pInputImage;
	};
/////////////////////////////////////////////////////////////////////////////////////////

	ImageSliceViewer::isisPrivate::isisPrivate()
	{
		m_pInputImage = new laVTKSinkFilter<quint8,3>();
	}

/////////////////////////////////////////////////////////////////////////////////////////

	ImageSliceViewer::ImageSliceViewer()
	{
		m_pPrivate = new isisPrivate;

		m_pPrivate->m_Actor         = vtkImageActor::New();
		m_pPrivate->m_Renderer      = vtkRenderer::New();
		m_pPrivate->m_RenderWindow  = vtkRenderWindow::New();

		m_pPrivate->m_Renderer->AddActor( m_pPrivate->m_Actor );

		m_pPrivate->m_Actor->Delete();

		m_pPrivate->m_Camera = m_pPrivate->m_Renderer->GetActiveCamera();
		m_pPrivate->m_Camera->ParallelProjectionOn();

		m_pPrivate->m_RenderWindow->AddRenderer( m_pPrivate->m_Renderer );

		m_pPrivate->m_Renderer->Delete();

		this->SetOrientation( Axial );

		InteractorObserver * observer = InteractorObserver::New();
		observer->SetImageSliceViewer( this );
		m_pPrivate->m_InteractorObserver = observer;

		m_pPrivate->m_Notifier      = itk::Object::New();

		m_pPrivate->m_NearPlane = 0.1;
		m_pPrivate->m_FarPlane  = 1000.0;

		m_pPrivate->m_ZoomFactor = 1.0;

		m_pPrivate->m_Renderer->SetBackground( 0, 0, 0 );

#ifdef NEED_SPHERE_ACTOR
		m_pPrivate->m_Sphere      = vtkSphereSource::New();
		m_pPrivate->m_SphereActor = vtkActor::New();  

		vtkPolyDataMapper * sphereMapper = vtkPolyDataMapper::New();

		sphereMapper->SetInput( m_pPrivate->m_Sphere->GetOutput() );  
		m_pPrivate->m_SphereActor->SetMapper( sphereMapper );
		m_pPrivate->m_Renderer->AddActor( m_pPrivate->m_SphereActor );

		m_pPrivate->m_Sphere->SetRadius(0.0f);

		sphereMapper->Delete();
#endif //def NEED_SPHERE_ACTOR
	}

/////////////////////////////////////////////////////////////////////////////////////////

	ImageSliceViewer
		::~ImageSliceViewer()
	{
		if( m_pPrivate->m_RenderWindow )
		{
			m_pPrivate->m_RenderWindow->Delete();
		}   

		if( m_pPrivate->m_InteractorObserver )
		{
			m_pPrivate->m_InteractorObserver->Delete();
		}


#ifdef NEED_SPHERE_ACTOR
		if( m_pPrivate->m_Sphere )
		{
			m_pPrivate->m_Sphere->Delete();
		}   

		if( m_pPrivate->m_SphereActor )
		{
			m_pPrivate->m_SphereActor->Delete();
		}    
#endif //def NEED_SPHERE_ACTOR

	}

/////////////////////////////////////////////////////////////////////////////////////////

	void
		ImageSliceViewer
		::Render()
	{
		UpdateInputFilter();
		
		m_pPrivate->m_Camera->SetClippingRange( 0.1, 100000 );
		m_pPrivate->m_RenderWindow->Render();
	}


	void
		ImageSliceViewer
		::SetInput( vtkImageData * image )
	{

		m_pPrivate->m_Actor->SetInput( image );
		this->SetupCamera();

	}

/////////////////////////////////////////////////////////////////////////////////////////

	laFilter* ImageSliceViewer::GetInputFilter()
	{
		return m_pPrivate->m_pInputImage;
	}

/////////////////////////////////////////////////////////////////////////////////////////



	void
		ImageSliceViewer
		::SetupCamera()
	{

		vtkImageData * image = m_pPrivate->m_Actor->GetInput();

		if ( !image )
		{
			return;
		}

		vtkFloatingPointType spacing[3];
		vtkFloatingPointType origin[3];
		int   dimensions[3];

		image->GetSpacing(spacing);
		image->GetOrigin(origin);
		image->GetDimensions(dimensions);

		double focalPoint[3];
		double position[3];

		int ext[6];
		image->GetExtent( ext );	

		for ( unsigned int cc = 0; cc < 3; cc++)
		{
			focalPoint[cc] = origin[cc] + ( spacing[cc] * dimensions[cc] ) / 2.0;
			position[cc]   = focalPoint[cc];
		}

		int idx = 0;

		double data[6];
		m_pPrivate->m_Actor->GetBounds(data);

		double* range = m_pPrivate->m_Actor->GetZRange();

		const double distanceToFocalPoint = 1000;
		switch( m_pPrivate->m_Orientation )
		{
		case Saggital:
			{
				idx = 0;
				position[0] -= distanceToFocalPoint;
				m_pPrivate->m_Camera->SetViewUp (     0,  0,  -1 );
				break;
			}
		case Coronal:
			{
				idx = 1;
				position[1] += distanceToFocalPoint;
				m_pPrivate->m_Camera->SetViewUp (     0,  0,  -1 );
				break;
			}
		case Axial:
			{
				idx = 2;
				position[2] -= distanceToFocalPoint;
				m_pPrivate->m_Camera->SetViewUp (     0,  -1,  0 );
				break;
			}
		}

		
		//position[idx] -= distanceToFocalPoint;

		m_pPrivate->m_Camera->SetPosition (   position );
		m_pPrivate->m_Camera->SetFocalPoint ( focalPoint );

#define myMAX(x,y) (((x)>(y))?(x):(y))  

		int d1 = (idx + 1) % 3;
		int d2 = (idx + 2) % 3;

		double max = myMAX( 
			spacing[d1] * dimensions[d1],
			spacing[d2] * dimensions[d2]);


		m_pPrivate->m_Camera->SetParallelScale( max / 2  * m_pPrivate->m_ZoomFactor );

	}


	void
		ImageSliceViewer
		::SetZoomFactor( double factor )
	{
		m_pPrivate->m_ZoomFactor = factor;
	}



	void
		ImageSliceViewer
		::SetInteractor( vtkRenderWindowInteractor * interactor )
	{
		m_pPrivate->m_RenderWindow->SetInteractor( interactor );

		vtkInteractorStyleImage * interactorStyle = vtkInteractorStyleImage::New();
		interactor->SetInteractorStyle( interactorStyle );
		interactorStyle->Delete();
		interactor->AddObserver( ::vtkCommand::RightButtonPressEvent, m_pPrivate->m_InteractorObserver );
		interactor->AddObserver( ::vtkCommand::LeftButtonPressEvent, m_pPrivate->m_InteractorObserver );
		interactor->AddObserver( ::vtkCommand::WindowLevelEvent, m_pPrivate->m_InteractorObserver );
		interactor->AddObserver( ::vtkCommand::RightButtonPressEvent, m_pPrivate->m_InteractorObserver );
		interactor->AddObserver( ::vtkCommand::RightButtonReleaseEvent, m_pPrivate->m_InteractorObserver );
		interactor->AddObserver( ::vtkCommand::MouseMoveEvent, m_pPrivate->m_InteractorObserver );
	}

	void
		ImageSliceViewer::SetOrientation( SliceOrientationType orientation )
	{
		m_pPrivate->m_Orientation = orientation;
		this->SetupCamera();
	}

	bool ImageSliceViewer::GetExtent(int & nFirstSlice, int & nLastSlice)
	{
		bool retVal = m_pPrivate->m_Actor->GetInput();
		if (retVal) {
			int ext[6];
			m_pPrivate->m_Actor->GetInput()->GetExtent( ext );		
			switch(m_pPrivate->m_Orientation) {
			case Saggital:
				nFirstSlice = ext[0];
				nLastSlice	= ext[1];
				break;
			case Coronal:
				nFirstSlice = ext[2];
				nLastSlice	= ext[3];
				break;
			case Axial:
				nFirstSlice = ext[4];
				nLastSlice	= ext[5];
				break;
			}
		}
			
		return retVal;
	}

	void
		ImageSliceViewer
		::SelectSlice( int slice )
	{
		if (!m_pPrivate->m_Actor->GetInput()) 
		{
			return;     // return, if no image is loaded yet.
		}

		int ext[6];
		m_pPrivate->m_Actor->GetInput()->GetExtent( ext );

		switch( m_pPrivate->m_Orientation )
		{
		case Saggital:
			if ((slice>=ext[0]) && (slice<=ext[1]))
			{
				ext[0] = slice;
				ext[1] = slice;
				m_pPrivate->m_SliceNum = slice;
			}
			break;
		case Coronal:
			if ((slice>=ext[2]) && (slice<=ext[3]))
			{
				ext[2] = slice;
				ext[3] = slice;
				m_pPrivate->m_SliceNum = slice;
			}
			break;
		case Axial:
			if ((slice>=ext[4]) && (slice<=ext[5]))
			{
				ext[4] = slice;
				ext[5] = slice;
				m_pPrivate->m_SliceNum = slice;
			}
			break;
		}

		m_pPrivate->m_Actor->SetDisplayExtent( ext );
	}


	void
		ImageSliceViewer
		::SelectPoint( int x, int y )
	{
		if (!m_pPrivate->m_Actor->GetInput()) 
		{
			return;     // return, if no image is loaded yet.
		}

		// Invert the y coordinate (vtk uses opposite y as Qt)
		// Not needed on Qt
		// int* winsize = m_RenderWindow->GetSize();
		// y = winsize[1] - y;

		// Convert display point to world point
		double wpoint[4];
		m_pPrivate->m_Renderer->SetDisplayPoint( x, y, 0 );
		m_pPrivate->m_Renderer->DisplayToWorld();
		m_pPrivate->m_Renderer->GetWorldPoint( wpoint );

		// Fix camera Z coordinate to match the current slice
		vtkFloatingPointType spacing[3]={1,1,1};
		vtkFloatingPointType origin[3] ={0,0,0};

		int dimensions[3] = { 100, 100, 100 };
		if ( m_pPrivate->m_Actor->GetInput() )
		{
			m_pPrivate->m_Actor->GetInput()->GetSpacing(spacing);
			m_pPrivate->m_Actor->GetInput()->GetOrigin(origin);
			m_pPrivate->m_Actor->GetInput()->GetDimensions(dimensions);
		}

		int idx = 0;
		switch( m_pPrivate->m_Orientation )
		{
		case Saggital:
			{
				idx = 0;
				break;
			}
		case Coronal:
			{
				idx = 1;
				break;
			}
		case Axial:
			{
				idx = 2;
				break;
			}
		}
		double realz = m_pPrivate->m_SliceNum * spacing[idx] + origin[idx];
		wpoint[idx] = realz;

		// At this point we have 3D position in the variable wpoint
		this->SelectPoint(wpoint[0], wpoint[1], wpoint[2]);

		m_pPrivate->m_Notifier->InvokeEvent( ClickedPointEvent() );
	}

	void  ImageSliceViewer::SelectPoint( double x, double y, double z )
	{
		if (!m_pPrivate->m_Actor->GetInput()) 
		{
			return;     // return, if no image is loaded yet.
		}
		m_pPrivate->m_SelectPoint[0] = x;
		m_pPrivate->m_SelectPoint[1] = y;
		m_pPrivate->m_SelectPoint[2] = z;

#ifdef NEED_SPHERE_ACTOR
		m_pPrivate->m_SphereActor->SetPosition( x, y, z );
#endif // def NEED_SPHERE_ACTOR

		int dimensions[3] = { 100, 100, 100 };

		if ( m_pPrivate->m_Actor->GetInput() )
		{
			m_pPrivate->m_Actor->GetInput()->GetDimensions(dimensions);

#ifdef NEED_SPHERE_ACTOR

			switch( m_Orientation )
			{
			case Saggital:
				m_pPrivate->m_Sphere->SetRadius(dimensions[0]/75);
				break;
			case Coronal:
				m_pPrivate->m_Sphere->SetRadius(dimensions[1]/75);
				break;
			case Axial:
				m_pPrivate->m_Sphere->SetRadius(dimensions[2]/75);
				break;
			}
#endif //def NEED_SPHERE_ACTOR

		}
	}

	void 
		ImageSliceViewer::GetSelectPoint(double data[3])
	{
		for(int i=0; i<3; i++)
		{
			data[i] = m_pPrivate->m_SelectPoint[i];
		}
	}

	unsigned long 
		ImageSliceViewer::AddObserver( const itk::EventObject & event, itk::Command * command)
	{
		return m_pPrivate->m_Notifier->AddObserver( event, command );
	}

	std::string ImageSliceViewer::GetOrientationName(SliceOrientationType orientation)
	{
		std::string retVal;
		switch(orientation) {
		case Axial:
			retVal = "Axial";
		break;
		case Coronal:
			retVal = "Coronal";
		break;
		case Saggital:
			retVal = "Saggital";
		break;
		}
		return retVal;
	}

/////////////////////////////////////////////////////////////////////////////////////////

	vtkRenderWindow* ImageSliceViewer::GetRenderWindow()
	{
		vtkRenderWindow* retVal = NULL;
		if (m_pPrivate != NULL) {
			retVal = m_pPrivate->m_RenderWindow;
		}
		return retVal;
	}

/////////////////////////////////////////////////////////////////////////////////////////

	void ImageSliceViewer::UpdateInputFilter()
	{
		vtkImageData* pImageData = dynamic_cast<vtkImageData*>(m_pPrivate->m_pInputImage->m_pData);
		if (pImageData != NULL) {
			SetInput(pImageData);
		}
	}
}



More information about the vtkusers mailing list