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