[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