NIREP

Wipe.cxx

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