NIREP
|
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