NIREP

Checkerboard.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003 Program:   vtkINRIA3D
00004 Module:    $Id: Checkerboard.cxx,v 1.19 2011/02/08 21:07:53 hawle Exp $
00005 Language:  C++
00006 Author:    $Author: hawle $
00007 Date:      $Date: 2011/02/08 21:07:53 $
00008 Version:   $Revision: 1.19 $
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 "Checkerboard.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 #include "vtkCheckerboardWidget.h"
00085 #include "vtkImageCheckerboard.h"
00086 #include "vtkCheckerboardRepresentation.h"
00087 //end of addition
00088 
00089 vtkCxxRevisionMacro(Checkerboard, "$Revision: 1.19 $");
00090 vtkStandardNewMacro(Checkerboard);
00091 
00092 
00093 Checkerboard::Checkerboard():NIREPvtkViewImage2D()
00094 {
00095   //Jeffrey Hawley added this
00096   this->SecondImage = NULL;
00097   this->CheckerboardWidget = vtkCheckerboardWidget::New();
00098   this->ImageCheckerboard = vtkImageCheckerboard::New();
00099   this->CheckerboardRepresentation = vtkCheckerboardRepresentation::New();
00100   this->ImageCheckerboard->SetNumberOfDivisions(2,2,1);
00101   //end of addition
00102 
00103   this->ImageResliceTwo     = vtkImageReslice::New();
00104 
00105   this->CheckerboardRepresentation->SetImageActor(this->ImageActor);
00106   this->CheckerboardRepresentation->SetCheckerboard(this->ImageCheckerboard);
00107 
00108   this->CheckerboardWidget->SetCurrentRenderer(this->GetRenderer());
00109   
00110   this->CheckerboardWidget->SetRepresentation(this->CheckerboardRepresentation);
00111 
00112   //for some reason if we take this out, then the image does not show up
00113   //I wonder if this will work
00114   this->GetWindowLevel()->Delete();
00115   this->WindowLevel      = vtkImageMapToColors::New();
00116   this->ImageReslice->SetInputConnection( this->WindowLevel->GetOutputPort() );
00117 
00118 
00119   this->WindowLevelTwo      = vtkImageMapToColors::New();
00120   this->MaskFilterTwo    = vtkImageBlendWithMask::New();
00121 
00122  
00123   this->ImageResliceTwo->SetOutputDimensionality(2);
00124   this->ImageResliceTwo->InterpolateOff();
00125   this->ImageResliceTwo->SetInputConnection( this->WindowLevelTwo->GetOutputPort() );
00126   
00127 
00128   this->AuxInputTwo     = this->WindowLevelTwo->GetOutput();
00129   this->ResliceInputTwo = this->WindowLevelTwo->GetOutput();
00130 
00131 
00132 
00133  
00134 }
00135 
00136 
00137 Checkerboard::~Checkerboard()
00138 {
00139   this->CheckerboardWidget->EnabledOff();
00140   this->CheckerboardWidget->Delete();
00141   this->ImageCheckerboard->Delete();
00142   this->CheckerboardRepresentation->Delete();
00143   
00144   this->WindowLevelTwo->Delete();
00145   this->ImageResliceTwo->Delete();
00146   this->SecondImage->UnRegister(this);
00147 
00148   this->MaskFilterTwo->Delete();
00149 }
00150 
00151 //void Checkerboard::InternalUpdate()
00152 //{
00153 //  this->UpdateImageActor();
00154 //  //this->UpdatePosition();
00155 //  this->InitializeImagePositionAndSize();
00156 //  
00157 //  //  this->UpdatePosition();
00158 //  
00159 //}
00160 
00161 
00167 //void Checkerboard::Initialize()
00168 //{
00169 //  this->Superclass::Initialize();
00170 //
00171 //  if (this->GetRenderer())
00172 //  {
00173 //    this->GetRenderer()->TwoSidedLightingOff();
00174 //  }
00175 //  
00176 //
00177 //}
00178 
00179 
00180 void Checkerboard::UpdateImageActor()
00181 {
00182   if(!this->SecondImage)
00183   {
00184     return;
00185   }
00186   if( !this->GetImage()  )
00187   {
00188     return;
00189   }
00190 
00196 
00197   //Since the image is already in ImageCheckerboard we just have
00198   //to do some updating of the ImageCheckerboard and pass
00199   //the information to the ImageActor.
00200   this->ImageReslice->GetOutput()->UpdateInformation();
00201   this->ImageResliceTwo->GetOutput()->UpdateInformation();
00202   this->ImageCheckerboard->GetOutput()->UpdateInformation();
00203   this->ImageActor->GetInput()->SetUpdateExtent(this->ImageCheckerboard->GetOutput()->GetWholeExtent());
00204   this->ImageActor->SetDisplayExtent(this->ImageCheckerboard->GetOutput()->GetWholeExtent());
00205   
00206   this->FirstRender = 1;
00207 }
00208 
00209 
00210 
00211 //Changes:
00212 //-Will need to do two ImagesReslices
00213 void Checkerboard::UpdatePosition ()
00214 {
00215   if(!this->SecondImage)
00216   {
00217     return;
00218   }
00219   if( !this->GetImage() )
00220   {
00221     return;
00222   }
00223   
00224   double x=0;
00225   double y=0;
00226   double max_x=0;
00227   double max_y=0;
00228   double min_x=0;
00229   double min_y=0;
00230   double pos[4];
00231 
00232   this->GetCurrentPoint(pos);
00233   pos[3] = 0.0;
00234 
00235   double* spacing = this->GetImage()->GetSpacing();
00236   double* origin  = this->GetImage()->GetOrigin();
00237 
00238   // check if pos lies inside image bounds
00239   //if( pos[0]<imBounds[0] || pos[0]>imBounds[1] ||
00240   //    pos[1]<imBounds[2] || pos[1]>imBounds[3] ||
00241   //    pos[2]<imBounds[4] || pos[2]>imBounds[5])
00242   //{
00243   //  // we are outside image bounds
00244   //  return;
00245   //}
00246 
00247 // round to the nearest integer slice
00248   pos[0] = vtkMath::Round ((pos[0]-origin[0])/spacing[0] )*spacing[0]+origin[0];
00249   pos[1] = vtkMath::Round ((pos[1]-origin[1])/spacing[1] )*spacing[1]+origin[1];
00250   pos[2] = vtkMath::Round ((pos[2]-origin[2])/spacing[2] )*spacing[2]+origin[2];
00251 
00252   /*
00253     double *bounds = this->ImageActor->GetBounds();
00254     min_x = bounds[0];
00255     max_x = bounds[1];
00256     min_y = bounds[2];
00257     max_y = bounds[3];
00258   */
00259 
00260   double min_bounds[4] = { this->GetWholeMinPosition(0),
00261                            this->GetWholeMinPosition(1),
00262                            this->GetWholeMinPosition(2),
00263                            0.0 };
00264 
00265   double max_bounds[4] = { this->GetWholeMaxPosition(0),
00266                            this->GetWholeMaxPosition(1),
00267                            this->GetWholeMaxPosition(2),
00268                            0.0 };
00269   
00270 
00271   // new efficient way to get the reslice origin and the axis coordinates.
00272   double reslice[4], pos2[4];
00273   this->ScreenToRealWorldMatrix->MultiplyPoint (pos, reslice);
00274   this->ImageReslice->SetResliceAxesOrigin(reslice[0], reslice[1], reslice[2]);
00275   this->ImageResliceTwo->SetResliceAxesOrigin(reslice[0], reslice[1], reslice[2]);
00276 
00277 
00278   vtkMatrix4x4* mat = vtkMatrix4x4::New();
00279   vtkMatrix4x4::Transpose (this->OrientationMatrix, mat);
00280   mat->MultiplyPoint (pos, pos2);
00281   mat->MultiplyPoint (min_bounds, min_bounds);
00282   mat->MultiplyPoint (max_bounds, max_bounds);
00283   mat->Delete();
00284 
00285   x = pos2[0];
00286   y = pos2[1];
00287 
00288   max_x = max_bounds[0];
00289   max_y = max_bounds[1];
00290   
00291   min_x = min_bounds[0];
00292   min_y = min_bounds[1];
00293 
00294   this->HorizontalLineSource->SetPoint1(min_x, y, 0.001);
00295   this->HorizontalLineSource->SetPoint2(max_x, y, 0.001);   
00296   this->VerticalLineSource->SetPoint1(x, min_y, 0.001);   
00297   this->VerticalLineSource->SetPoint2(x, max_y, 0.001);
00298 
00299   this->ImageReslice->Update(); // needed to update input Extent
00300   this->ImageResliceTwo->Update();
00301  
00302   int imCoor[3];
00303   this->GetCurrentVoxelCoordinates(imCoor);
00304   int dims[3];
00305   this->GetImage()->GetDimensions (dims);
00306       
00307   std::ostringstream os2;
00308   std::ostringstream os;
00309   //os << "Slice: ";
00310 
00311   os2 << "Zoom: " << this->GetZoom()*100.0 << " \%\n";
00312     
00313   switch( this->Orientation )
00314   {
00315       case NIREPvtkViewImage::AXIAL_ID :
00316         os << "Image size: " << dims[0] << " x " << dims[1] << "\n";
00317         os << "Voxel size: " << spacing[0] << " x " << spacing[1] << "\n";
00318         //os << imCoor[2] << " / " << dims[2]-1 << std::endl;
00319         os << "X: " << imCoor[0] << " px Y: " << imCoor[1] << " px Value: "
00320            << this->GetCurrentPointDoubleValue() << std::endl;
00321         os << "X: " << pos[0] << " mm Y: " << pos[1] << " mm\n";
00322         if ( this->ShowSliceNumber )
00323           os2 << "Slice: " << imCoor[2] << " / " << dims[2]-1 << std::endl;
00324         os2 << "Location: " << pos[2] << " mm";
00325         break;
00326           
00327         
00328       case NIREPvtkViewImage::CORONAL_ID :
00329         os << "Image size: " << dims[0] << " x " << dims[2] << "\n";
00330         os << "Voxel size: " << spacing[0] << " x " << spacing[2] << "\n";
00331         //os << imCoor[1] << " / " << dims[1]-1 << std::endl;
00332         os << "X: " << imCoor[0] << " px Z: " << imCoor[2] << " px Value: "
00333            << this->GetCurrentPointDoubleValue() << std::endl;
00334         os << "X: " << pos[0] << " mm Z: " << pos[2] << " mm\n";
00335         if ( this->ShowSliceNumber )
00336           os2 << "Slice: " << imCoor[1] << " / " << dims[1]-1 << std::endl;
00337         os2 << "Location: " << pos[1] << " mm";
00338         break;
00339         
00340         
00341       case NIREPvtkViewImage::SAGITTAL_ID :
00342         os << "Image size: " << dims[1] << " x " << dims[2] << "\n";
00343         os << "Voxel size: " << spacing[1] << " x " << spacing[2] << "\n";
00344         //os << imCoor[0] << " / " << dims[0]-1 << std::endl;
00345         os << "Y: " << imCoor[1] << " px Z: " << imCoor[2] << " px Value: "
00346            << this->GetCurrentPointDoubleValue() << std::endl;
00347         os << "Y: " << pos[1] << " mm Z: " << pos[2] << " mm\n";
00348         if ( this->ShowSliceNumber )
00349           os2 << "Slice: " << imCoor[0] << " / " << dims[0]-1 << std::endl;
00350         os2 << "Location: " << pos[0] << " mm";
00351         break;
00352   }
00353   os << "<window_level>";
00354   
00355   this->SetUpLeftAnnotation( os.str().c_str() );
00356   this->SetDownLeftAnnotation( os2.str().c_str() );
00357   //  }
00358   //  else
00359   //    this->SetUpRightAnnotation("");
00360   
00361   unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation());
00362   this->DataSetCutPlane->SetOrigin (reslice[0], reslice[1], reslice[2]);
00363   
00364   switch(direction)
00365   {
00366       case X_ID :
00367         //this->DataSetCutPlane->SetNormal (1,0,0);
00368         this->DataSetCutBox->SetBounds (this->DataSetCutPlane->GetOrigin()[0],this->DataSetCutPlane->GetOrigin()[0]+this->BoxThickness,
00369                                         this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1),
00370                                         this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2));
00371 
00372         break;
00373       case Y_ID :
00374         //this->DataSetCutPlane->SetNormal (0,1,0);
00375         this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0),
00376                                         this->DataSetCutPlane->GetOrigin()[1],this->DataSetCutPlane->GetOrigin()[1]+this->BoxThickness,
00377                                         this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2));
00378         break;
00379       case Z_ID :
00380         //this->DataSetCutPlane->SetNormal (0,0,1);
00381         this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0),
00382                                         this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1),
00383                                         this->DataSetCutPlane->GetOrigin()[2],this->DataSetCutPlane->GetOrigin()[2]+this->BoxThickness);
00384         break;
00385   }
00386 
00387 
00388   if( this->DataSetList.size() )
00389   {
00390 
00391     this->ResetAndRestablishZoomAndCamera();
00392 
00393     /*
00394       We need to correct for the origin of the actor. Indeed, the ImageActor
00395       has always position 0 in Z in axial view, in X in sagittal view and
00396       in Y in coronal view. The projected dataset have an origin that depends
00397       on the required slice and can be negative. In that case, the projected
00398       data are behind the image actor and thus not visible. Here, we correct
00399       this by translating the actor so that it becomes visible.
00400      */
00401     for( unsigned int i=0; i<this->DataSetActorList.size(); i++)
00402     {
00403       double Pos[3];
00404       this->DataSetActorList[i]->GetPosition (Pos);
00405 
00406       switch(direction)
00407       {
00408           case X_ID :
00409             Pos[0] = -1.0*reslice[0] + 1.0;
00410             break;
00411 
00412           case Y_ID:
00413             Pos[1] = -1.0*reslice[1] + 1.0;
00414             break;
00415 
00416           case Z_ID:
00417             Pos[2] = -1.0*reslice[2] + 1.0;
00418             break;
00419       }
00420 
00421       this->DataSetActorList[i]->SetPosition (Pos);
00422     }
00423 
00424   }
00425 
00426   this->Modified();
00427 }
00428 
00429 
00430 
00431 void Checkerboard::SetWindow (double w)
00432 {
00433 
00434   if( w<0.0 )
00435   {
00436     w = 0.0;
00437   }
00438 
00439   double shiftScaleWindow = this->GetShift() + w*this->GetScale();
00440   
00441   NIREPvtkViewImage::SetWindow ( shiftScaleWindow );
00442   this->WindowLevelForCorner->SetWindow( shiftScaleWindow );
00443   
00444   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00445   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00446 
00447   if( this->GetLookupTable() && this->WindowLevel->GetLookupTable())
00448   {
00449   
00450     this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00451                                        (v_max-1.5*this->GetShift())/this->GetScale());
00452     this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max);
00453     this->WindowLevelTwo->GetLookupTable()->SetRange (v_min, v_max);
00454   }
00455 
00456   if(this->BGWindowLevel && this->BGWindowLevel->GetLookupTable())
00457     this->BGWindowLevel->GetLookupTable()->SetRange( v_min, v_max);
00458 }
00459 
00460 
00461 
00462 void Checkerboard::SetLevel (double l)
00463 {
00464 
00465   double shiftScaleLevel = this->GetShift() + l*this->GetScale();
00466 
00467   NIREPvtkViewImage::SetLevel ( shiftScaleLevel );
00468   this->WindowLevelForCorner->SetLevel( shiftScaleLevel );
00469     
00470   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00471   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00472   
00473   if( this->GetLookupTable() )
00474   {
00475     this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00476                                        (v_max-1.5*this->GetShift())/this->GetScale());
00477     this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max);
00478     this->WindowLevelTwo->GetLookupTable()->SetRange (v_min, v_max);
00479   }
00480 }
00481 
00482 
00483 //Changes:
00484 //-Probably should get rid of this, but maybe not, will need to dicuss
00485 //to see how we want to deal with overlaps.
00486 void Checkerboard::SetSecondImage (vtkImageData* image)
00487 {
00488 
00489   if( !image )
00490   {
00491     return;
00492   }
00493   
00494   if(this->SecondImage != image)
00495   {
00496     if( this->SecondImage  != NULL )
00497     {
00498       this->SecondImage->UnRegister (this);
00499     }
00500     this->SecondImage = image;
00501     this->SecondImage->Register (this);
00502     int type = image->GetScalarType();
00503     int numberOfScalars = image->GetNumberOfScalarComponents();
00504     if( image->GetScalarType() == VTK_UNSIGNED_CHAR  && (image->GetNumberOfScalarComponents()==3 || image->GetNumberOfScalarComponents()==4) )
00505     {
00506       this->AuxInputTwo = image;
00507     }
00508     else
00509     //if(!( image->GetScalarType() == VTK_UNSIGNED_CHAR  && (image->GetNumberOfScalarComponents()==3 || image->GetNumberOfScalarComponents()==4) ))
00510     {
00511       this->WindowLevelTwo->SetInput (image);
00512       double range[2];
00513       image->GetScalarRange (range);
00514       if ( this->WindowLevelTwo->GetLookupTable() )
00515       {
00516         this->WindowLevelTwo->GetLookupTable()->SetRange (range);
00517       }
00518       this->AuxInputTwo = this->WindowLevelTwo->GetOutput();
00519     }
00520 
00521     if( this->GetMaskImage() )
00522     {
00523       this->MaskFilterTwo->SetImageInput ( this->AuxInputTwo );
00524     }
00525     else
00526     {
00527       this->ImageResliceTwo->SetInput ( this->AuxInputTwo );
00528       this->ResliceInputTwo = this->AuxInputTwo;
00529     }
00530 
00531 //    this->SetOrientation(this->Orientation);
00532       //this->ResliceInput = this->Blender->GetOutput();
00533     //}
00534   }
00535 
00536   if(this->GetImage())
00537   {
00538     if(this->GetSecondImage())
00539     {
00540       this->CheckerboardWidget->SetInteractor(this->GetRenderWindow()->GetInteractor());
00541       this->ImageCheckerboard->SetInput1(this->ImageReslice->GetOutput());
00542       this->ImageCheckerboard->SetInput2(this->ImageResliceTwo->GetOutput());
00543       this->ImageCheckerboard->Update();
00544       this->ImageActor->SetInput(this->ImageCheckerboard->GetOutput());
00545       this->AddActor(this->ImageActor);
00546       this->CheckerboardWidget->EnabledOn();
00547 
00548       this->AddActor(this->HorizontalLineActor);
00549       this->AddActor(this->VerticalLineActor);
00550 
00551   //this->AddActor(this->ImageActor);
00552 
00553 
00554 
00555   // Save the camera focal and position, and zoom, before calling InternalUpdate()
00556   double focal[3], pos[3], zoom;
00557   this->GetCameraFocalAndPosition (focal, pos);
00558   zoom = this->GetZoom();
00559   
00560 
00561   this->SetupAnnotations();
00562   this->InternalUpdate();
00563 
00564   
00565   // Check that the current displayed point lies within the bounds of the image. If not,
00566   // we camp it to the nearest acceptable position.
00567   double *wextent = image->GetBounds();
00568   double position[3];
00569   this->GetCurrentPoint ( position );
00570   position[0]<wextent[0]?position[0]=wextent[0]:position[0];
00571   position[0]>wextent[1]?position[0]=wextent[1]:position[0];
00572   position[1]<wextent[2]?position[1]=wextent[2]:position[1];
00573   position[1]>wextent[3]?position[1]=wextent[3]:position[1];
00574   position[2]<wextent[4]?position[2]=wextent[4]:position[2];
00575   position[2]>wextent[5]?position[2]=wextent[5]:position[2];
00576   this->SetCurrentPoint ( position );
00577 
00578   
00579     
00580   //this->SetWindow( this->GetWindow() );
00581   //this->SetLevel( this->GetLevel() );
00582 
00583 
00584   // restore the zoom and focal in case this is not the first time we render the image.
00585   if( !this->GetFirstImage() )
00586   {
00587     this->SetZoom ( zoom );
00588     this->SetCameraFocalAndPosition (focal, pos);
00589     this->SetFirstImage (0);
00590   }
00591 
00592   if( this->RulerWidgetVisibility )
00593     this->RulerWidget->On();
00594     }
00595   }
00596     
00597 }
00598 
00599 
00600 
00601 //Changes:
00602 //-Either need to create another SetImage, or have this SetImage place the images into an array
00603 //-Look into RegisterImage, I might have to do something else.
00604 //-I think I should create another SetImage
00605 void Checkerboard::SetImage(vtkImageData* image)
00606 {
00607   if(!image)
00608   {
00609     return;
00610   }
00611 
00612   int* extent = image->GetExtent();
00613   if( extent[1]<extent[0] || extent[3]<extent[2] || extent[5]<extent[4] )
00614   {
00615     vtkErrorMacro ( << "Image extent is not valid: " << extent[0] << " "
00616                     << extent[1] << " "
00617                     << extent[2] << " "
00618                     << extent[3] << " "
00619                     << extent[4] << " "
00620                     << extent[5]);
00621     return;
00622   }
00623   
00624 
00625   NIREPvtkViewImage::SetImage( image );
00626 
00627   // check if there is a mask image. If yes, then we check
00628   // if the new image size and spacing agrees with the mask image.
00629   // If not, we remove the mask image
00630   if( this->GetMaskImage() )
00631   {
00632     int*    dims        = image->GetDimensions();
00633     double* spacing     = image->GetSpacing();
00634     int*    maskDims    = this->GetMaskImage()->GetDimensions();
00635     double* maskSpacing = this->GetMaskImage()->GetSpacing();
00636 
00637     if( dims[0]!=maskDims[0] || dims[1]!=maskDims[1] || dims[2]!=maskDims[2] ||
00638         spacing[0]!=maskSpacing[0] || spacing[1]!=maskSpacing[1] || spacing[2]!=maskSpacing[2] )
00639     {
00640       this->RemoveMaskImage();
00641     }
00642   }
00643 
00644   // should check also the overlapping image
00645 
00646   if( image->GetScalarType() == VTK_UNSIGNED_CHAR  && (image->GetNumberOfScalarComponents()==3 || image->GetNumberOfScalarComponents()==4) )
00647   {
00648     this->AuxInput = image;
00649   }
00650   else
00651   {
00652     this->AuxInput = this->WindowLevel->GetOutput();
00653 
00654     this->WindowLevel->SetInput (image);
00655     double range[2];
00656     image->GetScalarRange (range);
00657     if ( this->WindowLevel->GetLookupTable() )
00658     {
00659       this->WindowLevel->GetLookupTable()->SetRange (range);
00660     }
00661   }
00662 
00663 
00664   if( this->GetOverlappingImage() )
00665   {
00666     this->Blender->SetInput (0, this->AuxInput );
00667   }
00668   else
00669   {
00670     if( this->GetMaskImage() )
00671     {
00672       this->MaskFilter->SetImageInput ( this->AuxInput );
00673     }
00674     else
00675     {
00676       this->ImageReslice->SetInput ( this->AuxInput );
00677       this->ResliceInput = this->AuxInput;
00678     }
00679   }
00680 
00681   //this->ImageActor->SetInput( this->ImageReslice->GetOutput() );
00682 
00683   if(this->GetImage())
00684   {
00685     if(this->GetSecondImage())
00686     {
00687       this->CheckerboardWidget->SetInteractor(this->GetRenderWindow()->GetInteractor());
00688       this->ImageCheckerboard->SetInput1(this->ImageReslice->GetOutput());
00689       this->ImageCheckerboard->SetInput2(this->ImageResliceTwo->GetOutput());
00690       this->ImageCheckerboard->Update();
00691       this->ImageActor->SetInput(this->ImageCheckerboard->GetOutput());
00692       this->AddActor(this->ImageActor);
00693       this->CheckerboardWidget->EnabledOn();
00694 
00695 
00696 
00697       this->AddActor(this->HorizontalLineActor);
00698       this->AddActor(this->VerticalLineActor);
00699 
00700       //this->AddActor(this->ImageActor);
00701 
00702 
00703 
00704       // Save the camera focal and position, and zoom, before calling InternalUpdate()
00705       double focal[3], pos[3], zoom;
00706       this->GetCameraFocalAndPosition (focal, pos);
00707       zoom = this->GetZoom();
00708       
00709 
00710       this->SetupAnnotations();
00711       this->InternalUpdate();
00712 
00713       
00714       // Check that the current displayed point lies within the bounds of the image. If not,
00715       // we camp it to the nearest acceptable position.
00716       double *wextent = image->GetBounds();
00717       double position[3];
00718       this->GetCurrentPoint ( position );
00719       position[0]<wextent[0]?position[0]=wextent[0]:position[0];
00720       position[0]>wextent[1]?position[0]=wextent[1]:position[0];
00721       position[1]<wextent[2]?position[1]=wextent[2]:position[1];
00722       position[1]>wextent[3]?position[1]=wextent[3]:position[1];
00723       position[2]<wextent[4]?position[2]=wextent[4]:position[2];
00724       position[2]>wextent[5]?position[2]=wextent[5]:position[2];
00725       this->SetCurrentPoint ( position );
00726 
00727 
00728       // restore the zoom and focal in case this is not the first time we render the image.
00729       if( !this->GetFirstImage() )
00730       {
00731         this->SetZoom ( zoom );
00732         this->SetCameraFocalAndPosition (focal, pos);
00733         this->SetFirstImage (0);
00734       }
00735 
00736       if( this->RulerWidgetVisibility )
00737         this->RulerWidget->On();
00738 
00739       }
00740   }
00741 }
00742 
00743 void Checkerboard::SetLookupTable (vtkScalarsToColors* lut)
00744 {
00745     
00746   if( !lut )
00747   {
00748     return;
00749   }
00750     
00751   NIREPvtkViewImage::SetLookupTable (lut);
00752 
00753   double v_min = this->GetLevel() - 0.5*this->GetWindow();
00754   double v_max = this->GetLevel() + 0.5*this->GetWindow();
00755 
00761   lut->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(),
00762                   (v_max-1.5*this->GetShift())/this->GetScale() );
00763 
00764   
00765   vtkLookupTable* realLut = vtkLookupTable::SafeDownCast (lut);
00766 
00767   if( !realLut )
00768   {
00769     std::cerr << "Error: Cannot cast vtkScalarsToColors to vtkLookupTable." << std::endl;
00770     return;
00771   }
00772   
00777   vtkLookupTable* newLut = vtkLookupTable::New();
00778   newLut->DeepCopy (realLut);
00779   newLut->SetRange (v_min, v_max);
00780   this->WindowLevel->SetLookupTable (newLut);
00781   newLut->Delete();
00782 
00783   vtkLookupTable* newLutTwo = vtkLookupTable::New();
00784   newLutTwo->DeepCopy (realLut);
00785   newLutTwo->SetRange (v_min, v_max);
00786   this->WindowLevelTwo->SetLookupTable (newLutTwo);
00787   newLutTwo->Delete();
00788   
00789 }
00790 
00791 
00792 void Checkerboard::SetOrientation(unsigned int p_orientation)
00793 {
00794   if( (p_orientation > vtkViewImage::NB_PLAN_IDS - 1) || (this->Orientation == p_orientation) )
00795   {
00796     return;
00797   }
00798 
00799   this->Orientation = p_orientation;
00800 
00801   
00802   // setup the OrientationMatrix and the ScreenToRealWorldMatrix. Then, we have no
00803   // need to check the view's orientation to determine what slice to display: a
00804   // simple matrix multiplication will tell it for us.
00805   this->OrientationMatrix->Zero();
00806   this->ScreenToRealWorldMatrix->Zero();
00807 
00808   
00809   if( this->Orientation == vtkViewImage::SAGITTAL_ID )
00810   {
00811     this->ImageReslice->SetResliceAxesDirectionCosines( 0, -1, 0,
00812                                                         0, 0, 1,
00813                                                         1, 0, 0);
00814           this->ImageResliceTwo->SetResliceAxesDirectionCosines( 0, -1, 0,
00815                                                         0, 0, 1,
00816                                                         1, 0, 0);
00817     this->OrientationMatrix->SetElement (0, 2, 0.0);
00818     this->OrientationMatrix->SetElement (1, 0, -1.0);
00819     this->OrientationMatrix->SetElement (2, 1, 1.0);
00820 
00821     this->ScreenToRealWorldMatrix->SetElement (0, 0, 1.0);
00822   }
00823 
00824   
00825   if( this->Orientation == vtkViewImage::CORONAL_ID )
00826   {
00827     if( this->Conventions == RADIOLOGIC )
00828     {
00829       this->OrientationMatrix->SetElement(0, 0, 1.0);
00830       this->ImageReslice->SetResliceAxesDirectionCosines(1,  0, 0,
00831                                                          0,  0, 1,
00832                                                          0,  1, 0); 
00833           this->ImageResliceTwo->SetResliceAxesDirectionCosines(1,  0, 0,
00834                                                          0,  0, 1,
00835                                                          0,  1, 0); 
00836     }
00837     else
00838     {  
00839       this->OrientationMatrix->SetElement(0, 0, -1.0);
00840       this->ImageReslice->SetResliceAxesDirectionCosines(-1,  0, 0,
00841                                                          0,  0, 1,
00842                                                          0,  1, 0); 
00843           this->ImageResliceTwo->SetResliceAxesDirectionCosines(-1,  0, 0,
00844                                                          0,  0, 1,
00845                                                          0,  1, 0); 
00846     }
00847     
00848     this->OrientationMatrix->SetElement(2, 1, 1.0);
00849     this->ScreenToRealWorldMatrix->SetElement (1, 1, 1.0);
00850   }
00851 
00852   
00853   if( this->Orientation == vtkViewImage::AXIAL_ID )
00854   {
00855 
00856     
00857     if( this->Conventions == RADIOLOGIC )
00858     {
00859       this->OrientationMatrix->SetElement(0, 0, 1.0 );
00860       this->ImageReslice->SetResliceAxesDirectionCosines(1, 0, 0,
00861                                                          0, 1, 0,
00862                                                          0, 0, 1);
00863             this->ImageResliceTwo->SetResliceAxesDirectionCosines(1, 0, 0,
00864                                                          0, 1, 0,
00865                                                          0, 0, 1);
00866     }
00867     else
00868     {  
00869       this->OrientationMatrix->SetElement(0, 0, -1.0 );
00870       this->ImageReslice->SetResliceAxesDirectionCosines(-1, 0, 0,
00871                                                          0, 1, 0,
00872                                                          0, 0, 1);
00873             this->ImageResliceTwo->SetResliceAxesDirectionCosines(-1, 0, 0,
00874                                                          0, 1, 0,
00875                                                          0, 0, 1);
00876     }
00877 
00878     this->OrientationMatrix->SetElement(1, 1, 1.0 );
00879     this->ScreenToRealWorldMatrix->SetElement (2, 2, 1.0);
00880   }
00881 
00882   unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation());
00883   switch(direction)
00884   {
00885       case X_ID :
00886         this->DataSetCutPlane->SetNormal (1,0,0);
00887         break;
00888       case Y_ID :
00889         this->DataSetCutPlane->SetNormal (0,1,0);
00890         break;
00891       case Z_ID :
00892         this->DataSetCutPlane->SetNormal (0,0,1);
00893         break;
00894   }
00895 
00896   //this->ImageReslice->Modified();
00897 
00898   this->UpdateImageActor(); // make sure update extent are up to date
00899   this->UpdatePosition(); // make sure reslicer origin are ok
00900   this->InitializeImagePositionAndSize(); // reset and center the view
00901   this->SetupAnnotations(); // make sure annotations are ok
00902   
00903   this->Modified();
00904   
00905 }
00906 
00907 
00908 
00909 vtkActor* Checkerboard::AddDataSet (vtkDataSet* dataset,  vtkProperty* property)
00910 {
00911 
00912   bool doit = true;
00913 
00914   if (!dataset)
00915     doit = false;
00916   
00917   if( this->HasDataSet (dataset) )
00918   {
00919     doit = false;
00920   }
00921   vtkImageData* imagedata = NULL;
00922   imagedata = vtkImageData::SafeDownCast(dataset);
00923   
00924   if (imagedata)
00925   {
00926     this->SetImage(imagedata);
00927   }
00928   else
00929   {
00930     
00931     if ( !this->GetImage() )
00932     {
00933       doit = false;
00934     }
00935     // don't constrain the memory of input datasets anymore.
00946     if (doit)
00947     {
00948       
00949       vtkMatrix4x4* matrix = vtkMatrix4x4::New();
00950       for (unsigned int i=0; i<3; i++)
00951       {
00952         for (unsigned int j=0; j<3; j++)
00953         {
00954           matrix->SetElement(i,j,this->ImageReslice->GetResliceAxes()->GetElement(j,i));
00955         }
00956         matrix->SetElement(i,3,0);
00957       }
00958       matrix->SetElement(3,3,1);
00959       
00960       vtkCutter* cutter = vtkCutter::New();
00961       cutter->SetCutFunction (this->DataSetCutPlane);
00962 
00963       // Very strangely in some cases (ex : landmarks)
00964       // the cutter increments the RefCount of the input dataset by 2
00965       // making some memory leek...
00966       // I could not manage to know what is wrong here
00967       
00968       cutter->SetInput (dataset);
00969       cutter->Update();
00970       
00971       if (!cutter->GetOutput())
00972       {
00973         vtkWarningMacro(<< "Unable to cut this dataset...");
00974         matrix->Delete();
00975         cutter->Delete();
00976         return NULL;
00977       }
00978       
00979       
00980       vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
00981       mapper->SetInput (cutter->GetOutput());
00982       
00983       vtkActor* actor = vtkActor::New();
00984       actor->SetUserMatrix (matrix);
00985       actor->SetMapper (mapper);
00986       if (property)
00987       {
00988         actor->SetProperty (property);
00989       }
00990 
00991       actor->PickableOff();
00992       
00993       this->AddActor (actor);
00994       this->DataSetList.push_back (dataset);
00995       this->DataSetActorList.push_back (actor);
00996 
00997       this->ResetAndRestablishZoomAndCamera();
00998 
00999       actor->Delete();
01000       mapper->Delete();
01001       matrix->Delete();
01002       cutter->Delete();
01003     }
01004   }
01005 
01006   
01007   return this->GetDataSetActor(dataset);
01008   
01009 }
01010 
01011 
01017 vtkActor* Checkerboard::SyncAddPolyData (vtkPolyData* polydata,  vtkProperty* property, double thickness)
01018 {
01019 
01020   if( this->IsLocked() )
01021   {
01022     return NULL;
01023   }
01024   
01025 
01026   vtkActor* actor = this->AddPolyData (polydata, property, thickness);
01027   
01028   this->Lock();
01029   for( unsigned int i=0; i<this->Children.size(); i++)
01030   {
01031 //     Checkerboard* view = dynamic_cast<Checkerboard*> (this->Children[i]);
01032     Checkerboard* view = Checkerboard::SafeDownCast (this->Children[i]);
01033     if( view )
01034     {
01035       view->SyncAddPolyData (polydata, property, thickness);
01036     }
01037   }
01038   this->UnLock();
01039 
01040   return actor;
01041   
01042   
01043 }
01044 
01045 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines