NIREP

Grid.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003 Program:   vtkINRIA3D
00004 Module:    $Id: Grid.cpp,v 1.1 2011/01/21 00:07:59 hawle Exp $
00005 Language:  C++
00006 Author:    $Author: hawle $
00007 Date:      $Date: 2011/01/21 00:07:59 $
00008 Version:   $Revision: 1.1 $
00009 
00010 Copyright (c) 2007 INRIA - Asclepios Project. All rights reserved.
00011 See Copyright.txt for details.
00012 
00013 This software is distributed WITHOUT ANY WARRANTY; without even
00014 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015 PURPOSE.  See the above copyright notices for more information.
00016 
00017 =========================================================================*/
00018 #include "Grid.h"
00019 
00020 #include "vtkInteractorObserver.h"
00021 #include "vtkInteractorStyleSwitch.h"
00022 #include "vtkRenderer.h"
00023 #include "vtkRenderWindow.h"
00024 #include "vtkRenderWindowInteractor.h"
00025 #include "vtkRendererCollection.h"
00026 #include "vtkProp.h"
00027 #include "vtkTextActor.h"
00028 #include "vtkCoordinate.h"
00029 #include "vtkProperty.h"
00030 #include "vtkProperty2D.h"
00031 #include "vtkTextProperty.h"
00032 #include <vtkCornerAnnotation.h>
00033 #include <vtkLightCollection.h>
00034 #include <vtkLight.h>
00035 #include "vtkOrientationAnnotation.h"
00036 
00037 #include "assert.h"
00038 #include <iostream>
00039 #include <sstream>
00040 #include <cmath>
00041 
00042 #include "NIREPvtkViewImage2DCommand.h"
00043 #include "vtkViewImage2DFullCommand.h"
00044 #include "NIREPvtkInteractorStyleImage2D.h"
00045 #include "vtkCamera.h"
00046 #include "vtkImageReslice.h"
00047 #include "vtkRenderWindow.h"
00048 #include "vtkTransform.h"
00049 #include "vtkImageMapToWindowLevelColors.h"
00050 #include "vtkImageMapToColors.h"
00051 #include "vtkImageActor.h"
00052 #include "vtkImageData.h"
00053 #include "vtkActor.h"
00054 #include "vtkPolyDataMapper.h"
00055 #include "vtkLineSource.h"
00056 #include "vtkLookupTable.h"
00057 #include "vtkImageBlendWithMask.h"
00058 #include "vtkImageBlend.h"
00059 #include <vtkPolyDataMapper2D.h>
00060 #include <vtkActor2D.h>
00061 
00062 #include <vtkColorTransferFunction.h>
00063 #include <vtkDataArray.h>
00064 #include <vtkPointData.h>
00065 #include <vtkCellData.h>
00066 #include <vtkExtractGeometry.h>
00067 #include <vtkDataSet.h>
00068 #include <vtkUnstructuredGrid.h>
00069 #include <vtkDataSetMapper.h>
00070 #include <vtkPlane.h>
00071 #include <vtkPlaneCollection.h>
00072 #include <vtkPolyDataMapper2D.h>
00073 #include <vtkActor2D.h>
00074 #include <vtkClipDataSet.h>
00075 #include <vtkCutter.h>
00076 #include <vtkBox.h>
00077 #include <vtkPolyDataWriter.h>
00078 #include <vtkPolyDataNormals.h>
00079 #include <vtkTransform.h>
00080 #include <vtkMath.h>
00081 #include <vtkRulerWidget.h>
00082 
00083 //Jeffrey Hawley added this
00084 //end of addition
00085 
00086 vtkCxxRevisionMacro(Grid, "$Revision: 1.1 $");
00087 vtkStandardNewMacro(Grid);
00088 
00089 
00090 Grid::Grid():NIREPvtkViewImage2D()
00091 {
00092   //Jeffrey Hawley added this
00093   deform = NULL;
00094   //end of addition
00095 
00096   this->FirstRender = 1;
00097   this->ShowSliceNumber  = 1;
00098   this->InteractionStyle = SELECT_INTERACTION;
00099   this->LeftButtonInteractionStyle = SELECT_INTERACTION;
00100   this->MiddleButtonInteractionStyle = SELECT_INTERACTION;
00101   this->RightButtonInteractionStyle = SELECT_INTERACTION;
00102   this->WheelInteractionStyle = SELECT_INTERACTION;
00103   this->RulerWidgetVisibility = 0;
00104   this->Show2DAxis = 1;
00105 
00106   this->Conventions = RADIOLOGIC;
00107   
00108   this->InitialParallelScale = 1.0;
00109 
00110 
00111   this->ImageReslice     = vtkImageReslice::New();
00112   this->ImageActor       = NULL;
00113 
00114   vtkRenderer *rend = this->GetRenderer();
00115 
00116   this->WindowLevelForCorner = vtkImageMapToWindowLevelColors::New();
00117   this->WindowLevel      = vtkImageMapToColors::New();
00118   this->MaskFilter       = vtkImageBlendWithMask::New();
00119   this->Blender          = vtkImageBlend::New();
00120 
00121   this->OrientationMatrix = vtkMatrix4x4::New();
00122   this->OrientationMatrix->Identity();
00123   this->ScreenToRealWorldMatrix = vtkMatrix4x4::New();
00124   this->ScreenToRealWorldMatrix->Zero();
00125   this->ScreenToRealWorldMatrix->SetElement (2, 2, 1.0);
00126 
00127   this->BGActor          = 0;
00128   this->BGWindowLevel    = 0;
00129   this->BGImage = 0;
00130 
00131   
00132   this->HorizontalLineSource = vtkLineSource::New();
00133   this->VerticalLineSource   = vtkLineSource::New();
00134   this->HorizontalLineActor  = vtkActor::New();
00135   this->VerticalLineActor    = vtkActor::New();
00136   
00137   this->DataSetCutPlane      = vtkPlane::New();
00138   this->DataSetCutBox        = vtkBox::New();
00139   
00140 
00141   this->DataSetCutPlane->SetOrigin (0,0,0);
00142   this->DataSetCutPlane->SetNormal (0,0,1);
00143   this->DataSetCutBox->SetBounds (0,0,0,0,0,0);
00144   this->BoxThickness = 2;
00145 
00146   // set the filters properties
00147   this->Blender->SetBlendModeToNormal();
00148   //this->Blender->SetOpacity (0,0.25 ); GEC 7/10/2010 changed to 50% opacity
00149   //this->Blender->SetOpacity (1, 0.75);
00150   this->Blender->SetOpacity (0,0.5);
00151   this->Blender->SetOpacity (1,0.5);
00152  
00153   
00154   
00155   // set up the vtk pipeline  
00156   this->ImageReslice->SetOutputDimensionality(2);
00157   this->ImageReslice->InterpolateOff();
00158   this->ImageReslice->SetInputConnection( this->WindowLevel->GetOutputPort() );
00159   
00160 
00161   this->AuxInput     = this->WindowLevel->GetOutput();
00162   this->ResliceInput = this->WindowLevel->GetOutput();
00163 
00164  
00165   // Interactor Style
00166   //this->InitInteractorStyle(Grid::SELECT_INTERACTION);
00167   this->SetInteractionStyle( NIREPvtkViewImage2D::SELECT_INTERACTION );
00168 
00169   
00170   // Initialize cursor lines
00171   vtkPolyDataMapper* mapper =  vtkPolyDataMapper::New();
00172   mapper->SetInputConnection( this->HorizontalLineSource->GetOutputPort() );
00173 
00174   this->HorizontalLineActor->SetMapper(mapper);
00175   this->HorizontalLineActor->GetProperty()->SetColor (1.0,0.0,0.0);
00176   mapper->Delete();
00177   this->HorizontalLineActor->SetVisibility (0);
00178   this->HorizontalLineActor->PickableOff();
00179   this->HorizontalLineActor->DragableOff();
00180   
00181 
00182   
00183   vtkPolyDataMapper* mapper2 =  vtkPolyDataMapper::New();
00184   mapper2->SetInputConnection( this->VerticalLineSource->GetOutputPort() );
00185   this->VerticalLineActor->SetMapper(mapper2);
00186   this->VerticalLineActor->GetProperty()->SetColor (1.0,0.0,0.0);
00187   mapper2->Delete();
00188   this->VerticalLineActor->SetVisibility (0);
00189   this->VerticalLineActor->PickableOff();
00190   this->VerticalLineActor->DragableOff();
00191 
00192   this->GetCornerAnnotation()->SetWindowLevel ( this->WindowLevelForCorner );
00193   
00194   this->SetOrientation (NIREPvtkViewImage::AXIAL_ID);
00195 
00196   if( NIREPvtkViewImage2D::GetViewImage2DDisplayConventions()==0 )
00197   {
00198     this->SetConventionsToRadiological();
00199   }
00200   else
00201   {
00202     this->SetConventionsToNeurological();
00203   }
00204 
00205   this->RulerWidget = vtkRulerWidget::New();
00206   this->RulerWidget->KeyPressActivationOff();
00207   
00208 }
00209 
00210 
00211 Grid::~Grid()
00212 {
00213   if(deform) {
00214     delete deform;
00215   }
00216 }
00217 
00218 //void Grid::InternalUpdate()
00219 //{
00220 //  this->UpdateImageActor();
00221 //  //this->UpdatePosition();
00222 //  this->InitializeImagePositionAndSize();
00223 //  
00224 //  //  this->UpdatePosition();
00225 //  
00226 //}
00227 
00228 
00234 //void Grid::Initialize()
00235 //{
00236 //  this->Superclass::Initialize();
00237 //
00238 //  if (this->GetRenderer())
00239 //  {
00240 //    this->GetRenderer()->TwoSidedLightingOff();
00241 //  }
00242 //  
00243 //
00244 //}
00245 
00246 
00247 void Grid::UpdateImageActor()
00248 {
00249   if( !this->GetImage()  )
00250   {
00251     return;
00252   }
00253   //vtkPolyData *pd = vtkPolyData::New();
00254   //int * dimensions = this->ImageReslice->GetOutput()->GetDimensions();
00255   //this->ImageReslice->GetOutput()->SetScalarTypeToDouble();
00256   //double *scalarPointer = (double*)this->ImageReslice->GetOutput()->GetScalarPointer();
00257   //vtkPoints *points = vtkPoints::New();
00258   //for(int i=0; i<dimensions[0]*dimensions[1]*dimensions[2]; i=i+3) {
00259   //    points->InsertNextPoint(scalarPointer[i],scalarPointer[i+1],scalarPointer[i+2]);
00260   //}
00261 
00262   //pd->SetPoints(points);
00263   //
00264   //vtkArrowSource* as = vtkArrowSource::New();
00265   //vtkGlyph3D* gl = vtkGlyph3D::New();
00266   //gl->SetInput(pd);
00267   //gl->SetSource(as->GetOutput());
00268   //gl->SetScaleModeToScaleByVector();
00269   //gl->SetScaleFactor(0.1);
00270   //vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
00271   //mapper->SetInputConnection(gl->GetOutputPort());
00272   //    
00273   //m_vectorActor->SetMapper(mapper);
00274   this->FirstRender = 1;
00275 }
00276 
00277 
00278 
00279 //Changes:
00280 //-Will need to do two ImagesReslices
00281 void Grid::UpdatePosition ()
00282 {
00283   if( !this->GetImage() )
00284   {
00285     return;
00286   }
00287   
00288   double x=0;
00289   double y=0;
00290   double max_x=0;
00291   double max_y=0;
00292   double min_x=0;
00293   double min_y=0;
00294   double pos[4];
00295 
00296   this->GetCurrentPoint(pos);
00297   pos[3] = 0.0;
00298 
00299   double* spacing = this->GetImage()->GetSpacing();
00300   double* origin  = this->GetImage()->GetOrigin();
00301 
00302   // check if pos lies inside image bounds
00303   //if( pos[0]<imBounds[0] || pos[0]>imBounds[1] ||
00304   //    pos[1]<imBounds[2] || pos[1]>imBounds[3] ||
00305   //    pos[2]<imBounds[4] || pos[2]>imBounds[5])
00306   //{
00307   //  // we are outside image bounds
00308   //  return;
00309   //}
00310 
00311 // round to the nearest integer slice
00312   pos[0] = vtkMath::Round ((pos[0]-origin[0])/spacing[0] )*spacing[0]+origin[0];
00313   pos[1] = vtkMath::Round ((pos[1]-origin[1])/spacing[1] )*spacing[1]+origin[1];
00314   pos[2] = vtkMath::Round ((pos[2]-origin[2])/spacing[2] )*spacing[2]+origin[2];
00315 
00316   /*
00317     double *bounds = this->ImageActor->GetBounds();
00318     min_x = bounds[0];
00319     max_x = bounds[1];
00320     min_y = bounds[2];
00321     max_y = bounds[3];
00322   */
00323 
00324   double min_bounds[4] = { this->GetWholeMinPosition(0),
00325                            this->GetWholeMinPosition(1),
00326                            this->GetWholeMinPosition(2),
00327                            0.0 };
00328 
00329   double max_bounds[4] = { this->GetWholeMaxPosition(0),
00330                            this->GetWholeMaxPosition(1),
00331                            this->GetWholeMaxPosition(2),
00332                            0.0 };
00333   
00334 
00335   // new efficient way to get the reslice origin and the axis coordinates.
00336   double reslice[4], pos2[4];
00337   this->ScreenToRealWorldMatrix->MultiplyPoint (pos, reslice);
00338   this->ImageReslice->SetResliceAxesOrigin(reslice[0], reslice[1], reslice[2]);
00339 
00340 
00341   vtkMatrix4x4* mat = vtkMatrix4x4::New();
00342   vtkMatrix4x4::Transpose (this->OrientationMatrix, mat);
00343   mat->MultiplyPoint (pos, pos2);
00344   mat->MultiplyPoint (min_bounds, min_bounds);
00345   mat->MultiplyPoint (max_bounds, max_bounds);
00346   mat->Delete();
00347 
00348   x = pos2[0];
00349   y = pos2[1];
00350 
00351   max_x = max_bounds[0];
00352   max_y = max_bounds[1];
00353   
00354   min_x = min_bounds[0];
00355   min_y = min_bounds[1];
00356 
00357   this->HorizontalLineSource->SetPoint1(min_x, y, 0.001);
00358   this->HorizontalLineSource->SetPoint2(max_x, y, 0.001);   
00359   this->VerticalLineSource->SetPoint1(x, min_y, 0.001);   
00360   this->VerticalLineSource->SetPoint2(x, max_y, 0.001);
00361 
00362   this->ImageReslice->Update(); // needed to update input Extent
00363  
00364   int imCoor[3];
00365   this->GetCurrentVoxelCoordinates(imCoor);
00366   int dims[3];
00367   this->GetImage()->GetDimensions (dims);
00368       
00369   std::ostringstream os2;
00370   std::ostringstream os;
00371   //os << "Slice: ";
00372 
00373   os2 << "Zoom: " << this->GetZoom()*100.0 << " \%\n";
00374     
00375   switch( this->Orientation )
00376   {
00377       case NIREPvtkViewImage::AXIAL_ID :
00378         os << "Image size: " << dims[0] << " x " << dims[1] << "\n";
00379         os << "Voxel size: " << spacing[0] << " x " << spacing[1] << "\n";
00380         //os << imCoor[2] << " / " << dims[2]-1 << std::endl;
00381         os << "X: " << imCoor[0] << " px Y: " << imCoor[1] << " px Value: "
00382            << this->GetCurrentPointDoubleValue() << std::endl;
00383         os << "X: " << pos[0] << " mm Y: " << pos[1] << " mm\n";
00384         if ( this->ShowSliceNumber )
00385           os2 << "Slice: " << imCoor[2] << " / " << dims[2]-1 << std::endl;
00386         os2 << "Location: " << pos[2] << " mm";
00387         break;
00388           
00389         
00390       case NIREPvtkViewImage::CORONAL_ID :
00391         os << "Image size: " << dims[0] << " x " << dims[2] << "\n";
00392         os << "Voxel size: " << spacing[0] << " x " << spacing[2] << "\n";
00393         //os << imCoor[1] << " / " << dims[1]-1 << std::endl;
00394         os << "X: " << imCoor[0] << " px Z: " << imCoor[2] << " px Value: "
00395            << this->GetCurrentPointDoubleValue() << std::endl;
00396         os << "X: " << pos[0] << " mm Z: " << pos[2] << " mm\n";
00397         if ( this->ShowSliceNumber )
00398           os2 << "Slice: " << imCoor[1] << " / " << dims[1]-1 << std::endl;
00399         os2 << "Location: " << pos[1] << " mm";
00400         break;
00401         
00402         
00403       case NIREPvtkViewImage::SAGITTAL_ID :
00404         os << "Image size: " << dims[1] << " x " << dims[2] << "\n";
00405         os << "Voxel size: " << spacing[1] << " x " << spacing[2] << "\n";
00406         //os << imCoor[0] << " / " << dims[0]-1 << std::endl;
00407         os << "Y: " << imCoor[1] << " px Z: " << imCoor[2] << " px Value: "
00408            << this->GetCurrentPointDoubleValue() << std::endl;
00409         os << "Y: " << pos[1] << " mm Z: " << pos[2] << " mm\n";
00410         if ( this->ShowSliceNumber )
00411           os2 << "Slice: " << imCoor[0] << " / " << dims[0]-1 << std::endl;
00412         os2 << "Location: " << pos[0] << " mm";
00413         break;
00414   }
00415   os << "<window_level>";
00416   
00417   this->SetUpLeftAnnotation( os.str().c_str() );
00418   this->SetDownLeftAnnotation( os2.str().c_str() );
00419   //  }
00420   //  else
00421   //    this->SetUpRightAnnotation("");
00422   
00423   unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation());
00424   this->DataSetCutPlane->SetOrigin (reslice[0], reslice[1], reslice[2]);
00425   
00426   switch(direction)
00427   {
00428       case X_ID :
00429         //this->DataSetCutPlane->SetNormal (1,0,0);
00430         this->DataSetCutBox->SetBounds (this->DataSetCutPlane->GetOrigin()[0],this->DataSetCutPlane->GetOrigin()[0]+this->BoxThickness,
00431                                         this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1),
00432                                         this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2));
00433 
00434         break;
00435       case Y_ID :
00436         //this->DataSetCutPlane->SetNormal (0,1,0);
00437         this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0),
00438                                         this->DataSetCutPlane->GetOrigin()[1],this->DataSetCutPlane->GetOrigin()[1]+this->BoxThickness,
00439                                         this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2));
00440         break;
00441       case Z_ID :
00442         //this->DataSetCutPlane->SetNormal (0,0,1);
00443         this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0),
00444                                         this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1),
00445                                         this->DataSetCutPlane->GetOrigin()[2],this->DataSetCutPlane->GetOrigin()[2]+this->BoxThickness);
00446         break;
00447   }
00448 
00449 
00450   if( this->DataSetList.size() )
00451   {
00452 
00453     this->ResetAndRestablishZoomAndCamera();
00454 
00455     /*
00456       We need to correct for the origin of the actor. Indeed, the ImageActor
00457       has always position 0 in Z in axial view, in X in sagittal view and
00458       in Y in coronal view. The projected dataset have an origin that depends
00459       on the required slice and can be negative. In that case, the projected
00460       data are behind the image actor and thus not visible. Here, we correct
00461       this by translating the actor so that it becomes visible.
00462      */
00463     for( unsigned int i=0; i<this->DataSetActorList.size(); i++)
00464     {
00465       double Pos[3];
00466       this->DataSetActorList[i]->GetPosition (Pos);
00467 
00468       switch(direction)
00469       {
00470           case X_ID :
00471             Pos[0] = -1.0*reslice[0] + 1.0;
00472             break;
00473 
00474           case Y_ID:
00475             Pos[1] = -1.0*reslice[1] + 1.0;
00476             break;
00477 
00478           case Z_ID:
00479             Pos[2] = -1.0*reslice[2] + 1.0;
00480             break;
00481       }
00482 
00483       this->DataSetActorList[i]->SetPosition (Pos);
00484     }
00485 
00486   }
00487 
00488   this->Modified();
00489 }
00490 
00491 
00492 
00493 void Grid::SetWindow (double w)
00494 {
00495 
00496   if( w<0.0 )
00497   {
00498     w = 0.0;
00499   }
00500 
00501   double shiftScaleWindow = this->GetShift() + w*this->GetScale();
00502   
00503   NIREPvtkViewImage::SetWindow ( shiftScaleWindow );
00504   this->WindowLevelForCorner->SetWindow( shiftScaleWindow );
00505   
00506   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00507   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00508 
00509   if( this->GetLookupTable() && this->WindowLevel->GetLookupTable())
00510   {
00511   
00512     this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00513                                        (v_max-1.5*this->GetShift())/this->GetScale());
00514     this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max);
00515   }
00516 
00517   if(this->BGWindowLevel && this->BGWindowLevel->GetLookupTable())
00518     this->BGWindowLevel->GetLookupTable()->SetRange( v_min, v_max);
00519 }
00520 
00521 
00522 
00523 void Grid::SetLevel (double l)
00524 {
00525 
00526   double shiftScaleLevel = this->GetShift() + l*this->GetScale();
00527 
00528   NIREPvtkViewImage::SetLevel ( shiftScaleLevel );
00529   this->WindowLevelForCorner->SetLevel( shiftScaleLevel );
00530     
00531   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00532   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00533   
00534   if( this->GetLookupTable() )
00535   {
00536     this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00537                                        (v_max-1.5*this->GetShift())/this->GetScale());
00538     this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max);
00539   }
00540 }
00541 
00542 
00543 
00544 //Changes:
00545 //-Either need to create another SetImage, or have this SetImage place the images into an array
00546 //-Look into RegisterImage, I might have to do something else.
00547 //-I think I should create another SetImage
00548 void Grid::SetImage(gec::Deform<double>* imageTwo)
00549 {
00550   if(!imageTwo)
00551   {
00552     return;
00553   }
00554   gec::Transformation *imagethree;
00555 
00556 
00557 
00558   deform = imageTwo;
00559 
00560   vtkImageData *image = imageTwo->GetImage()->GetVTKData();
00561 
00562   int* extent = image->GetExtent();
00563   if( extent[1]<extent[0] || extent[3]<extent[2] || extent[5]<extent[4] )
00564   {
00565     vtkErrorMacro ( << "Image extent is not valid: " << extent[0] << " "
00566                     << extent[1] << " "
00567                     << extent[2] << " "
00568                     << extent[3] << " "
00569                     << extent[4] << " "
00570                     << extent[5]);
00571     return;
00572   }
00573 
00574   
00575 
00576   NIREPvtkViewImage::SetImage( image );
00577 
00578   // check if there is a mask image. If yes, then we check
00579   // if the new image size and spacing agrees with the mask image.
00580   // If not, we remove the mask image
00581   if( this->GetMaskImage() )
00582   {
00583     int*    dims        = image->GetDimensions();
00584     double* spacing     = image->GetSpacing();
00585     int*    maskDims    = this->GetMaskImage()->GetDimensions();
00586     double* maskSpacing = this->GetMaskImage()->GetSpacing();
00587 
00588     if( dims[0]!=maskDims[0] || dims[1]!=maskDims[1] || dims[2]!=maskDims[2] ||
00589         spacing[0]!=maskSpacing[0] || spacing[1]!=maskSpacing[1] || spacing[2]!=maskSpacing[2] )
00590     {
00591       this->RemoveMaskImage();
00592     }
00593   }
00594 
00595   // should check also the overlapping image
00596   int type = image->GetScalarType();
00597   int components = image->GetNumberOfScalarComponents();
00598   if( image->GetScalarType() == VTK_UNSIGNED_CHAR  && (image->GetNumberOfScalarComponents()==3 || image->GetNumberOfScalarComponents()==4) )
00599   {
00600     this->AuxInput = image;
00601   }
00602   else if(image->GetScalarType() == VTK_FLOAT && image->GetNumberOfScalarComponents()==3) {
00603     this->AuxInput = image;
00604   }
00605   else
00606   {
00607     this->AuxInput = this->WindowLevel->GetOutput();
00608 
00609     this->WindowLevel->SetInput (image);
00610     double range[2];
00611     image->GetScalarRange (range);
00612     if ( this->WindowLevel->GetLookupTable() )
00613     {
00614       this->WindowLevel->GetLookupTable()->SetRange (range);
00615     }
00616   }
00617 
00618 
00619   if( this->GetOverlappingImage() )
00620   {
00621     this->Blender->SetInput (0, this->AuxInput );
00622   }
00623   else
00624   {
00625     if( this->GetMaskImage() )
00626     {
00627       this->MaskFilter->SetImageInput ( this->AuxInput );
00628     }
00629     else
00630     {
00631       this->ImageReslice->SetInput ( this->AuxInput );
00632       this->ResliceInput = this->AuxInput;
00633     }
00634   }
00635 
00636   //this->ImageActor->SetInput( this->ImageReslice->GetOutput() );
00637 
00638   if(this->GetImage())
00639   {
00640       this->AddActor(this->HorizontalLineActor);
00641       this->AddActor(this->VerticalLineActor);
00642 
00643       //this->AddActor();
00644 
00645       // Save the camera focal and position, and zoom, before calling InternalUpdate()
00646       double focal[3], pos[3], zoom;
00647       this->GetCameraFocalAndPosition (focal, pos);
00648       zoom = this->GetZoom();
00649       
00650 
00651       this->SetupAnnotations();
00652       this->InternalUpdate();
00653 
00654       
00655       // Check that the current displayed point lies within the bounds of the image. If not,
00656       // we camp it to the nearest acceptable position.
00657       double *wextent = image->GetBounds();
00658       double position[3];
00659       this->GetCurrentPoint ( position );
00660       position[0]<wextent[0]?position[0]=wextent[0]:position[0];
00661       position[0]>wextent[1]?position[0]=wextent[1]:position[0];
00662       position[1]<wextent[2]?position[1]=wextent[2]:position[1];
00663       position[1]>wextent[3]?position[1]=wextent[3]:position[1];
00664       position[2]<wextent[4]?position[2]=wextent[4]:position[2];
00665       position[2]>wextent[5]?position[2]=wextent[5]:position[2];
00666       this->SetCurrentPoint ( position );
00667 
00668 
00669       // restore the zoom and focal in case this is not the first time we render the image.
00670       if( !this->GetFirstImage() )
00671       {
00672         this->SetZoom ( zoom );
00673         this->SetCameraFocalAndPosition (focal, pos);
00674         this->SetFirstImage (0);
00675       }
00676 
00677       if( this->RulerWidgetVisibility )
00678         this->RulerWidget->On();
00679 
00680   }
00681 }
00682 
00683 void Grid::SetLookupTable (vtkScalarsToColors* lut)
00684 {
00685     
00686   if( !lut )
00687   {
00688     return;
00689   }
00690     
00691   NIREPvtkViewImage::SetLookupTable (lut);
00692 
00693   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00694   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00695 
00701   lut->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00702                   (v_max-1.5*this->GetShift())/this->GetScale() );
00703 
00704   
00705   vtkLookupTable* realLut = vtkLookupTable::SafeDownCast (lut);
00706 
00707   if( !realLut )
00708   {
00709     std::cerr << "Error: Cannot cast vtkScalarsToColors to vtkLookupTable." << std::endl;
00710     return;
00711   }
00712   
00717   vtkLookupTable* newLut = vtkLookupTable::New();
00718   newLut->DeepCopy (realLut);
00719   newLut->SetRange (v_min, v_max);
00720   this->WindowLevel->SetLookupTable (newLut);
00721   newLut->Delete();
00722   
00723 }
00724 
00725 
00726 void Grid::SetOrientation(unsigned int p_orientation)
00727 {
00728   if( (p_orientation > vtkViewImage::NB_PLAN_IDS - 1) || (this->Orientation == p_orientation) )
00729   {
00730     return;
00731   }
00732 
00733   this->Orientation = p_orientation;
00734 
00735   
00736   // setup the OrientationMatrix and the ScreenToRealWorldMatrix. Then, we have no
00737   // need to check the view's orientation to determine what slice to display: a
00738   // simple matrix multiplication will tell it for us.
00739   this->OrientationMatrix->Zero();
00740   this->ScreenToRealWorldMatrix->Zero();
00741 
00742   
00743   if( this->Orientation == vtkViewImage::SAGITTAL_ID )
00744   {
00745     this->ImageReslice->SetResliceAxesDirectionCosines( 0, -1, 0,
00746                                                         0, 0, 1,
00747                                                         1, 0, 0);
00748     this->OrientationMatrix->SetElement (0, 2, 0.0);
00749     this->OrientationMatrix->SetElement (1, 0, -1.0);
00750     this->OrientationMatrix->SetElement (2, 1, 1.0);
00751 
00752     this->ScreenToRealWorldMatrix->SetElement (0, 0, 1.0);
00753   }
00754 
00755   
00756   if( this->Orientation == vtkViewImage::CORONAL_ID )
00757   {
00758     if( this->Conventions == RADIOLOGIC )
00759     {
00760       this->OrientationMatrix->SetElement(0, 0, 1.0);
00761       this->ImageReslice->SetResliceAxesDirectionCosines(1,  0, 0,
00762                                                          0,  0, 1,
00763                                                          0,  1, 0); 
00764     }
00765     else
00766     {  
00767       this->OrientationMatrix->SetElement(0, 0, -1.0);
00768       this->ImageReslice->SetResliceAxesDirectionCosines(-1,  0, 0,
00769                                                          0,  0, 1,
00770                                                          0,  1, 0); 
00771     }
00772     
00773     this->OrientationMatrix->SetElement(2, 1, 1.0);
00774     this->ScreenToRealWorldMatrix->SetElement (1, 1, 1.0);
00775   }
00776 
00777   
00778   if( this->Orientation == vtkViewImage::AXIAL_ID )
00779   {
00780 
00781     
00782     if( this->Conventions == RADIOLOGIC )
00783     {
00784       this->OrientationMatrix->SetElement(0, 0, 1.0 );
00785       this->ImageReslice->SetResliceAxesDirectionCosines(1, 0, 0,
00786                                                          0, 1, 0,
00787                                                          0, 0, 1);
00788     }
00789     else
00790     {  
00791       this->OrientationMatrix->SetElement(0, 0, -1.0 );
00792       this->ImageReslice->SetResliceAxesDirectionCosines(-1, 0, 0,
00793                                                          0, 1, 0,
00794                                                          0, 0, 1);
00795     }
00796 
00797     this->OrientationMatrix->SetElement(1, 1, 1.0 );
00798     this->ScreenToRealWorldMatrix->SetElement (2, 2, 1.0);
00799   }
00800 
00801   unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation());
00802   switch(direction)
00803   {
00804       case X_ID :
00805         this->DataSetCutPlane->SetNormal (1,0,0);
00806         break;
00807       case Y_ID :
00808         this->DataSetCutPlane->SetNormal (0,1,0);
00809         break;
00810       case Z_ID :
00811         this->DataSetCutPlane->SetNormal (0,0,1);
00812         break;
00813   }
00814 
00815   //this->ImageReslice->Modified();
00816 
00817   this->UpdateImageActor(); // make sure update extent are up to date
00818   this->UpdatePosition(); // make sure reslicer origin are ok
00819   this->InitializeImagePositionAndSize(); // reset and center the view
00820   this->SetupAnnotations(); // make sure annotations are ok
00821   
00822   this->Modified();
00823   
00824 }
00825 
00826 
00827 
00828 vtkActor* Grid::AddDataSet (vtkDataSet* dataset,  vtkProperty* property)
00829 {
00830 
00831   bool doit = true;
00832 
00833   if (!dataset)
00834     doit = false;
00835   
00836   if( this->HasDataSet (dataset) )
00837   {
00838     doit = false;
00839   }
00840   vtkImageData* imagedata = NULL;
00841   imagedata = vtkImageData::SafeDownCast(dataset);
00842   
00843   if (imagedata)
00844   {
00845     this->SetImage(imagedata);
00846   }
00847   else
00848   {
00849     
00850     if ( !this->GetImage() )
00851     {
00852       doit = false;
00853     }
00854     // don't constrain the memory of input datasets anymore.
00865     if (doit)
00866     {
00867       
00868       vtkMatrix4x4* matrix = vtkMatrix4x4::New();
00869       for (unsigned int i=0; i<3; i++)
00870       {
00871         for (unsigned int j=0; j<3; j++)
00872         {
00873           matrix->SetElement(i,j,this->ImageReslice->GetResliceAxes()->GetElement(j,i));
00874         }
00875         matrix->SetElement(i,3,0);
00876       }
00877       matrix->SetElement(3,3,1);
00878       
00879       vtkCutter* cutter = vtkCutter::New();
00880       cutter->SetCutFunction (this->DataSetCutPlane);
00881 
00882       // Very strangely in some cases (ex : landmarks)
00883       // the cutter increments the RefCount of the input dataset by 2
00884       // making some memory leek...
00885       // I could not manage to know what is wrong here
00886       
00887       cutter->SetInput (dataset);
00888       cutter->Update();
00889       
00890       if (!cutter->GetOutput())
00891       {
00892         vtkWarningMacro(<< "Unable to cut this dataset...");
00893         matrix->Delete();
00894         cutter->Delete();
00895         return NULL;
00896       }
00897       
00898       
00899       vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
00900       mapper->SetInput (cutter->GetOutput());
00901       
00902       vtkActor* actor = vtkActor::New();
00903       actor->SetUserMatrix (matrix);
00904       actor->SetMapper (mapper);
00905       if (property)
00906       {
00907         actor->SetProperty (property);
00908       }
00909 
00910       actor->PickableOff();
00911       
00912       this->AddActor (actor);
00913       this->DataSetList.push_back (dataset);
00914       this->DataSetActorList.push_back (actor);
00915 
00916       this->ResetAndRestablishZoomAndCamera();
00917 
00918       actor->Delete();
00919       mapper->Delete();
00920       matrix->Delete();
00921       cutter->Delete();
00922     }
00923   }
00924 
00925   
00926   return this->GetDataSetActor(dataset);
00927   
00928 }
00929 
00930 
00936 vtkActor* Grid::SyncAddPolyData (vtkPolyData* polydata,  vtkProperty* property, double thickness)
00937 {
00938 
00939   if( this->IsLocked() )
00940   {
00941     return NULL;
00942   }
00943   
00944 
00945   vtkActor* actor = this->AddPolyData (polydata, property, thickness);
00946   
00947   this->Lock();
00948   for( unsigned int i=0; i<this->Children.size(); i++)
00949   {
00950 //     Grid* view = dynamic_cast<Grid*> (this->Children[i]);
00951     Grid* view = Grid::SafeDownCast (this->Children[i]);
00952     if( view )
00953     {
00954       view->SyncAddPolyData (polydata, property, thickness);
00955     }
00956   }
00957   this->UnLock();
00958 
00959   return actor;
00960   
00961   
00962 }
00963 
00964 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines