NIREP
|
00001 /*========================================================================= 00002 00003 Program: vtkINRIA3D 00004 Module: $Id: VectorField.cpp,v 1.6 2011/01/25 23:48:18 hawle Exp $ 00005 Language: C++ 00006 Author: $Author: hawle $ 00007 Date: $Date: 2011/01/25 23:48:18 $ 00008 Version: $Revision: 1.6 $ 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 "VectorField.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 <vtkArrowSource.h> 00085 #include <vtkGlyph3D.h> 00086 #include <vtkVertex.h> 00087 #include <vtkPoints.h> 00088 #include <vtkStructuredGridReader.h> 00089 #include <vtkVoxel.h> 00090 #include <vtkCellArray.h> 00091 #include <vtkDataArray.h> 00092 #include <vtkFloatArray.h> 00093 #include <vtkDoubleArray.h> 00094 #include <vtkStructuredGrid.h> 00095 #include <vtkGlyph2D.h> 00096 #include <vtkLookupTableManager.h> 00097 //end of addition 00098 00099 vtkCxxRevisionMacro(VectorField, "$Revision: 1.6 $"); 00100 vtkStandardNewMacro(VectorField); 00101 00102 00103 VectorField::VectorField():NIREPvtkViewImage2D() 00104 { 00105 //Jeffrey Hawley added this 00106 m_vectorActor = vtkActor::New(); 00107 // InitializeArrays(); 00108 //end of addition 00109 00110 this->FirstRender = 1; 00111 this->ShowSliceNumber = 1; 00112 this->InteractionStyle = SELECT_INTERACTION; 00113 this->LeftButtonInteractionStyle = SELECT_INTERACTION; 00114 this->MiddleButtonInteractionStyle = SELECT_INTERACTION; 00115 this->RightButtonInteractionStyle = SELECT_INTERACTION; 00116 this->WheelInteractionStyle = SELECT_INTERACTION; 00117 this->RulerWidgetVisibility = 0; 00118 this->Show2DAxis = 1; 00119 00120 this->Conventions = RADIOLOGIC; 00121 00122 this->InitialParallelScale = 1.0; 00123 00124 00125 this->ImageReslice = vtkImageReslice::New(); 00126 this->ImageActor = NULL; 00127 00128 vtkRenderer *rend = this->GetRenderer(); 00129 00130 this->WindowLevelForCorner = vtkImageMapToWindowLevelColors::New(); 00131 this->WindowLevel = vtkImageMapToColors::New(); 00132 this->MaskFilter = vtkImageBlendWithMask::New(); 00133 this->Blender = vtkImageBlend::New(); 00134 00135 this->OrientationMatrix = vtkMatrix4x4::New(); 00136 this->OrientationMatrix->Identity(); 00137 this->ScreenToRealWorldMatrix = vtkMatrix4x4::New(); 00138 this->ScreenToRealWorldMatrix->Zero(); 00139 this->ScreenToRealWorldMatrix->SetElement (2, 2, 1.0); 00140 00141 this->BGActor = 0; 00142 this->BGWindowLevel = 0; 00143 this->BGImage = 0; 00144 00145 00146 this->HorizontalLineSource = vtkLineSource::New(); 00147 this->VerticalLineSource = vtkLineSource::New(); 00148 this->HorizontalLineActor = vtkActor::New(); 00149 this->VerticalLineActor = vtkActor::New(); 00150 00151 this->DataSetCutPlane = vtkPlane::New(); 00152 this->DataSetCutBox = vtkBox::New(); 00153 00154 00155 this->DataSetCutPlane->SetOrigin (0,0,0); 00156 this->DataSetCutPlane->SetNormal (0,0,1); 00157 this->DataSetCutBox->SetBounds (0,0,0,0,0,0); 00158 this->BoxThickness = 2; 00159 00160 // set the filters properties 00161 this->Blender->SetBlendModeToNormal(); 00162 //this->Blender->SetOpacity (0,0.25 ); GEC 7/10/2010 changed to 50% opacity 00163 //this->Blender->SetOpacity (1, 0.75); 00164 this->Blender->SetOpacity (0,0.5); 00165 this->Blender->SetOpacity (1,0.5); 00166 00167 00168 00169 // set up the vtk pipeline 00170 this->ImageReslice->SetOutputDimensionality(2); 00171 this->ImageReslice->InterpolateOff(); 00172 this->ImageReslice->SetInputConnection( this->WindowLevel->GetOutputPort() ); 00173 00174 00175 this->AuxInput = this->WindowLevel->GetOutput(); 00176 this->ResliceInput = this->WindowLevel->GetOutput(); 00177 00178 00179 // Interactor Style 00180 //this->InitInteractorStyle(VectorField::SELECT_INTERACTION); 00181 this->SetInteractionStyle( NIREPvtkViewImage2D::SELECT_INTERACTION ); 00182 00183 00184 // Initialize cursor lines 00185 vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); 00186 mapper->SetInputConnection( this->HorizontalLineSource->GetOutputPort() ); 00187 00188 this->HorizontalLineActor->SetMapper(mapper); 00189 this->HorizontalLineActor->GetProperty()->SetColor (1.0,0.0,0.0); 00190 mapper->Delete(); 00191 this->HorizontalLineActor->SetVisibility (0); 00192 this->HorizontalLineActor->PickableOff(); 00193 this->HorizontalLineActor->DragableOff(); 00194 00195 00196 00197 vtkPolyDataMapper* mapper2 = vtkPolyDataMapper::New(); 00198 mapper2->SetInputConnection( this->VerticalLineSource->GetOutputPort() ); 00199 this->VerticalLineActor->SetMapper(mapper2); 00200 this->VerticalLineActor->GetProperty()->SetColor (1.0,0.0,0.0); 00201 mapper2->Delete(); 00202 this->VerticalLineActor->SetVisibility (0); 00203 this->VerticalLineActor->PickableOff(); 00204 this->VerticalLineActor->DragableOff(); 00205 00206 this->GetCornerAnnotation()->SetWindowLevel ( this->WindowLevelForCorner ); 00207 00208 this->SetOrientation (NIREPvtkViewImage::AXIAL_ID); 00209 00210 if( NIREPvtkViewImage2D::GetViewImage2DDisplayConventions()==0 ) 00211 { 00212 this->SetConventionsToRadiological(); 00213 } 00214 else 00215 { 00216 this->SetConventionsToNeurological(); 00217 } 00218 00219 this->RulerWidget = vtkRulerWidget::New(); 00220 this->RulerWidget->KeyPressActivationOff(); 00221 00222 } 00223 00224 00225 VectorField::~VectorField() 00226 { 00227 } 00228 00229 //void VectorField::InternalUpdate() 00230 //{ 00231 // this->UpdateImageActor(); 00232 // //this->UpdatePosition(); 00233 // this->InitializeImagePositionAndSize(); 00234 // 00235 // // this->UpdatePosition(); 00236 // 00237 //} 00238 00239 00245 //void VectorField::Initialize() 00246 //{ 00247 // this->Superclass::Initialize(); 00248 // 00249 // if (this->GetRenderer()) 00250 // { 00251 // this->GetRenderer()->TwoSidedLightingOff(); 00252 // } 00253 // 00254 // 00255 //} 00256 00257 00258 void VectorField::UpdateImageActor() 00259 { 00260 if( !this->GetImage() ) 00261 { 00262 return; 00263 } 00264 //vtkPolyData *pd = vtkPolyData::New(); 00265 //int * dimensions = this->ImageReslice->GetOutput()->GetDimensions(); 00266 //this->ImageReslice->GetOutput()->SetScalarTypeToDouble(); 00267 //double *scalarPointer = (double*)this->ImageReslice->GetOutput()->GetScalarPointer(); 00268 //vtkPoints *points = vtkPoints::New(); 00269 //for(int i=0; i<dimensions[0]*dimensions[1]*dimensions[2]; i=i+3) { 00270 // points->InsertNextPoint(scalarPointer[i],scalarPointer[i+1],scalarPointer[i+2]); 00271 //} 00272 00273 //pd->SetPoints(points); 00274 // 00275 //vtkArrowSource* as = vtkArrowSource::New(); 00276 //vtkGlyph3D* gl = vtkGlyph3D::New(); 00277 //gl->SetInput(pd); 00278 //gl->SetSource(as->GetOutput()); 00279 //gl->SetScaleModeToScaleByVector(); 00280 //gl->SetScaleFactor(0.1); 00281 //vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); 00282 //mapper->SetInputConnection(gl->GetOutputPort()); 00283 // 00284 //m_vectorActor->SetMapper(mapper); 00285 this->FirstRender = 1; 00286 } 00287 00288 00289 00290 //Changes: 00291 //-Will need to do two ImagesReslices 00292 void VectorField::UpdatePosition () 00293 { 00294 if( !this->GetImage() ) 00295 { 00296 return; 00297 } 00298 00299 double x=0; 00300 double y=0; 00301 double max_x=0; 00302 double max_y=0; 00303 double min_x=0; 00304 double min_y=0; 00305 double pos[4]; 00306 00307 this->GetCurrentPoint(pos); 00308 pos[3] = 0.0; 00309 00310 double* spacing = this->GetImage()->GetSpacing(); 00311 double* origin = this->GetImage()->GetOrigin(); 00312 00313 // check if pos lies inside image bounds 00314 //if( pos[0]<imBounds[0] || pos[0]>imBounds[1] || 00315 // pos[1]<imBounds[2] || pos[1]>imBounds[3] || 00316 // pos[2]<imBounds[4] || pos[2]>imBounds[5]) 00317 //{ 00318 // // we are outside image bounds 00319 // return; 00320 //} 00321 00322 // round to the nearest integer slice 00323 pos[0] = vtkMath::Round ((pos[0]-origin[0])/spacing[0] )*spacing[0]+origin[0]; 00324 pos[1] = vtkMath::Round ((pos[1]-origin[1])/spacing[1] )*spacing[1]+origin[1]; 00325 pos[2] = vtkMath::Round ((pos[2]-origin[2])/spacing[2] )*spacing[2]+origin[2]; 00326 00327 /* 00328 double *bounds = this->ImageActor->GetBounds(); 00329 min_x = bounds[0]; 00330 max_x = bounds[1]; 00331 min_y = bounds[2]; 00332 max_y = bounds[3]; 00333 */ 00334 00335 double min_bounds[4] = { this->GetWholeMinPosition(0), 00336 this->GetWholeMinPosition(1), 00337 this->GetWholeMinPosition(2), 00338 0.0 }; 00339 00340 double max_bounds[4] = { this->GetWholeMaxPosition(0), 00341 this->GetWholeMaxPosition(1), 00342 this->GetWholeMaxPosition(2), 00343 0.0 }; 00344 00345 00346 // new efficient way to get the reslice origin and the axis coordinates. 00347 double reslice[4], pos2[4]; 00348 this->ScreenToRealWorldMatrix->MultiplyPoint (pos, reslice); 00349 this->ImageReslice->SetResliceAxesOrigin(reslice[0], reslice[1], reslice[2]); 00350 00351 00352 vtkMatrix4x4* mat = vtkMatrix4x4::New(); 00353 vtkMatrix4x4::Transpose (this->OrientationMatrix, mat); 00354 mat->MultiplyPoint (pos, pos2); 00355 mat->MultiplyPoint (min_bounds, min_bounds); 00356 mat->MultiplyPoint (max_bounds, max_bounds); 00357 mat->Delete(); 00358 00359 x = pos2[0]; 00360 y = pos2[1]; 00361 00362 max_x = max_bounds[0]; 00363 max_y = max_bounds[1]; 00364 00365 min_x = min_bounds[0]; 00366 min_y = min_bounds[1]; 00367 00368 this->HorizontalLineSource->SetPoint1(min_x, y, 0.001); 00369 this->HorizontalLineSource->SetPoint2(max_x, y, 0.001); 00370 this->VerticalLineSource->SetPoint1(x, min_y, 0.001); 00371 this->VerticalLineSource->SetPoint2(x, max_y, 0.001); 00372 00373 this->ImageReslice->Update(); // needed to update input Extent 00374 00375 int imCoor[3]; 00376 this->GetCurrentVoxelCoordinates(imCoor); 00377 int dims[3]; 00378 this->GetImage()->GetDimensions (dims); 00379 00380 std::ostringstream os2; 00381 std::ostringstream os; 00382 //os << "Slice: "; 00383 00384 os2 << "Zoom: " << this->GetZoom()*100.0 << " \%\n"; 00385 00386 switch( this->Orientation ) 00387 { 00388 case NIREPvtkViewImage::AXIAL_ID : 00389 os << "Image size: " << dims[0] << " x " << dims[1] << "\n"; 00390 os << "Voxel size: " << spacing[0] << " x " << spacing[1] << "\n"; 00391 //os << imCoor[2] << " / " << dims[2]-1 << std::endl; 00392 os << "X: " << imCoor[0] << " px Y: " << imCoor[1] << " px Value: " 00393 << this->GetCurrentPointDoubleValue() << std::endl; 00394 os << "X: " << pos[0] << " mm Y: " << pos[1] << " mm\n"; 00395 if ( this->ShowSliceNumber ) 00396 os2 << "Slice: " << imCoor[2] << " / " << dims[2]-1 << std::endl; 00397 os2 << "Location: " << pos[2] << " mm"; 00398 break; 00399 00400 00401 case NIREPvtkViewImage::CORONAL_ID : 00402 os << "Image size: " << dims[0] << " x " << dims[2] << "\n"; 00403 os << "Voxel size: " << spacing[0] << " x " << spacing[2] << "\n"; 00404 //os << imCoor[1] << " / " << dims[1]-1 << std::endl; 00405 os << "X: " << imCoor[0] << " px Z: " << imCoor[2] << " px Value: " 00406 << this->GetCurrentPointDoubleValue() << std::endl; 00407 os << "X: " << pos[0] << " mm Z: " << pos[2] << " mm\n"; 00408 if ( this->ShowSliceNumber ) 00409 os2 << "Slice: " << imCoor[1] << " / " << dims[1]-1 << std::endl; 00410 os2 << "Location: " << pos[1] << " mm"; 00411 break; 00412 00413 00414 case NIREPvtkViewImage::SAGITTAL_ID : 00415 os << "Image size: " << dims[1] << " x " << dims[2] << "\n"; 00416 os << "Voxel size: " << spacing[1] << " x " << spacing[2] << "\n"; 00417 //os << imCoor[0] << " / " << dims[0]-1 << std::endl; 00418 os << "Y: " << imCoor[1] << " px Z: " << imCoor[2] << " px Value: " 00419 << this->GetCurrentPointDoubleValue() << std::endl; 00420 os << "Y: " << pos[1] << " mm Z: " << pos[2] << " mm\n"; 00421 if ( this->ShowSliceNumber ) 00422 os2 << "Slice: " << imCoor[0] << " / " << dims[0]-1 << std::endl; 00423 os2 << "Location: " << pos[0] << " mm"; 00424 break; 00425 } 00426 os << "<window_level>"; 00427 00428 this->SetUpLeftAnnotation( os.str().c_str() ); 00429 this->SetDownLeftAnnotation( os2.str().c_str() ); 00430 // } 00431 // else 00432 // this->SetUpRightAnnotation(""); 00433 00434 unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation()); 00435 this->DataSetCutPlane->SetOrigin (reslice[0], reslice[1], reslice[2]); 00436 00437 switch(direction) 00438 { 00439 case X_ID : 00440 //this->DataSetCutPlane->SetNormal (1,0,0); 00441 this->DataSetCutBox->SetBounds (this->DataSetCutPlane->GetOrigin()[0],this->DataSetCutPlane->GetOrigin()[0]+this->BoxThickness, 00442 this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1), 00443 this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2)); 00444 00445 break; 00446 case Y_ID : 00447 //this->DataSetCutPlane->SetNormal (0,1,0); 00448 this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0), 00449 this->DataSetCutPlane->GetOrigin()[1],this->DataSetCutPlane->GetOrigin()[1]+this->BoxThickness, 00450 this->GetWholeMinPosition(2),this->GetWholeMaxPosition(2)); 00451 break; 00452 case Z_ID : 00453 //this->DataSetCutPlane->SetNormal (0,0,1); 00454 this->DataSetCutBox->SetBounds (this->GetWholeMinPosition(0),this->GetWholeMaxPosition(0), 00455 this->GetWholeMinPosition(1),this->GetWholeMaxPosition(1), 00456 this->DataSetCutPlane->GetOrigin()[2],this->DataSetCutPlane->GetOrigin()[2]+this->BoxThickness); 00457 break; 00458 } 00459 00460 00461 if( this->DataSetList.size() ) 00462 { 00463 00464 this->ResetAndRestablishZoomAndCamera(); 00465 00466 /* 00467 We need to correct for the origin of the actor. Indeed, the ImageActor 00468 has always position 0 in Z in axial view, in X in sagittal view and 00469 in Y in coronal view. The projected dataset have an origin that depends 00470 on the required slice and can be negative. In that case, the projected 00471 data are behind the image actor and thus not visible. Here, we correct 00472 this by translating the actor so that it becomes visible. 00473 */ 00474 for( unsigned int i=0; i<this->DataSetActorList.size(); i++) 00475 { 00476 double Pos[3]; 00477 this->DataSetActorList[i]->GetPosition (Pos); 00478 00479 switch(direction) 00480 { 00481 case X_ID : 00482 Pos[0] = -1.0*reslice[0] + 1.0; 00483 break; 00484 00485 case Y_ID: 00486 Pos[1] = -1.0*reslice[1] + 1.0; 00487 break; 00488 00489 case Z_ID: 00490 Pos[2] = -1.0*reslice[2] + 1.0; 00491 break; 00492 } 00493 00494 this->DataSetActorList[i]->SetPosition (Pos); 00495 } 00496 00497 } 00498 00499 this->Modified(); 00500 } 00501 00502 00503 00504 void VectorField::SetWindow (double w) 00505 { 00506 00507 if( w<0.0 ) 00508 { 00509 w = 0.0; 00510 } 00511 00512 double shiftScaleWindow = this->GetShift() + w*this->GetScale(); 00513 00514 NIREPvtkViewImage::SetWindow ( shiftScaleWindow ); 00515 this->WindowLevelForCorner->SetWindow( shiftScaleWindow ); 00516 00517 double v_min = this->GetLevel() - 0.5*this->GetWindow(); 00518 double v_max = this->GetLevel() + 0.5*this->GetWindow(); 00519 00520 if( this->GetLookupTable() && this->WindowLevel->GetLookupTable()) 00521 { 00522 00523 this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(), 00524 (v_max-1.5*this->GetShift())/this->GetScale()); 00525 this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max); 00526 } 00527 00528 if(this->BGWindowLevel && this->BGWindowLevel->GetLookupTable()) 00529 this->BGWindowLevel->GetLookupTable()->SetRange( v_min, v_max); 00530 } 00531 00532 00533 00534 void VectorField::SetLevel (double l) 00535 { 00536 00537 double shiftScaleLevel = this->GetShift() + l*this->GetScale(); 00538 00539 NIREPvtkViewImage::SetLevel ( shiftScaleLevel ); 00540 this->WindowLevelForCorner->SetLevel( shiftScaleLevel ); 00541 00542 double v_min = this->GetLevel() - 0.5*this->GetWindow(); 00543 double v_max = this->GetLevel() + 0.5*this->GetWindow(); 00544 00545 if( this->GetLookupTable() ) 00546 { 00547 this->GetLookupTable()->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(), 00548 (v_max-1.5*this->GetShift())/this->GetScale()); 00549 this->WindowLevel->GetLookupTable()->SetRange (v_min, v_max); 00550 } 00551 } 00552 00553 00554 00555 //Changes: 00556 //-Either need to create another SetImage, or have this SetImage place the images into an array 00557 //-Look into RegisterImage, I might have to do something else. 00558 //-I think I should create another SetImage 00559 void VectorField::SetImage(vtkImageData* image) 00560 { 00561 //vtkStructuredGridReader *reader = vtkStructuredGridReader::New(); 00562 //reader->SetFileName("subset.vtk"); 00563 //reader->Update(); 00564 00565 //vtkArrowSource* as = vtkArrowSource::New(); 00566 //vtkGlyph3D* gl = vtkGlyph3D::New(); 00567 //gl->SetInputConnection(reader->GetOutputPort()); 00568 //gl->SetSource(as->GetOutput()); 00569 //gl->SetScaleModeToScaleByVector(); 00570 //gl->SetScaleFactor(0.1); 00571 00572 //vtkLookupTable* lu = vtkLookupTable::New(); 00573 //lu->SetNumberOfTableValues(256); 00574 //lu->SetHueRange(0.6667, 0); 00575 //lu->SetTableRange(0, 5); 00576 //lu->SetVectorMode(vtkScalarsToColors::MAGNITUDE); 00577 //lu->Build(); 00578 00579 //vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); 00580 //mapper->SetInputConnection(gl->GetOutputPort()); 00581 //mapper->SetLookupTable(lu); 00582 //gl->Update(); 00583 //m_vectorActor->SetMapper(mapper); 00584 00585 //this->AddActor(m_vectorActor); 00586 00587 //NIREPvtkViewImage::SetImage( image ); 00588 if(!image) 00589 { 00590 return; 00591 } 00592 00593 int* extent = image->GetExtent(); 00594 if( extent[1]<extent[0] || extent[3]<extent[2] || extent[5]<extent[4] ) 00595 { 00596 vtkErrorMacro ( << "Image extent is not valid: " << extent[0] << " " 00597 << extent[1] << " " 00598 << extent[2] << " " 00599 << extent[3] << " " 00600 << extent[4] << " " 00601 << extent[5]); 00602 return; 00603 } 00604 00605 00606 00607 NIREPvtkViewImage::SetImage( image ); 00608 00609 // check if there is a mask image. If yes, then we check 00610 // if the new image size and spacing agrees with the mask image. 00611 // If not, we remove the mask image 00612 if( this->GetMaskImage() ) 00613 { 00614 int* dims = image->GetDimensions(); 00615 double* spacing = image->GetSpacing(); 00616 int* maskDims = this->GetMaskImage()->GetDimensions(); 00617 double* maskSpacing = this->GetMaskImage()->GetSpacing(); 00618 00619 if( dims[0]!=maskDims[0] || dims[1]!=maskDims[1] || dims[2]!=maskDims[2] || 00620 spacing[0]!=maskSpacing[0] || spacing[1]!=maskSpacing[1] || spacing[2]!=maskSpacing[2] ) 00621 { 00622 this->RemoveMaskImage(); 00623 } 00624 } 00625 00626 // should check also the overlapping image 00627 int type = image->GetScalarType(); 00628 int components = image->GetNumberOfScalarComponents(); 00629 if( image->GetScalarType() == VTK_UNSIGNED_CHAR && (image->GetNumberOfScalarComponents()==3 || image->GetNumberOfScalarComponents()==4) ) 00630 { 00631 this->AuxInput = image; 00632 } 00633 else if(image->GetScalarType() == VTK_FLOAT && image->GetNumberOfScalarComponents()==3) { 00634 this->AuxInput = image; 00635 } 00636 else 00637 { 00638 this->AuxInput = this->WindowLevel->GetOutput(); 00639 00640 this->WindowLevel->SetInput (image); 00641 double range[2]; 00642 image->GetScalarRange (range); 00643 if ( this->WindowLevel->GetLookupTable() ) 00644 { 00645 this->WindowLevel->GetLookupTable()->SetRange (range); 00646 } 00647 } 00648 00649 00650 if( this->GetOverlappingImage() ) 00651 { 00652 this->Blender->SetInput (0, this->AuxInput ); 00653 } 00654 else 00655 { 00656 if( this->GetMaskImage() ) 00657 { 00658 this->MaskFilter->SetImageInput ( this->AuxInput ); 00659 } 00660 else 00661 { 00662 this->ImageReslice->SetInput ( this->AuxInput ); 00663 this->ResliceInput = this->AuxInput; 00664 } 00665 } 00666 00667 //this->ImageActor->SetInput( this->ImageReslice->GetOutput() ); 00668 00669 if(this->GetImage()) 00670 { 00671 this->AddActor(this->HorizontalLineActor); 00672 this->AddActor(this->VerticalLineActor); 00673 00674 //this->AddActor(this->ImageActor); 00675 vtkStructuredGrid *pd = vtkStructuredGrid::New(); 00676 //vtkPolyData *pd = vtkPolyData::New(); 00677 this->ImageReslice->Update(); 00678 int * dimensions = this->ImageReslice->GetOutput()->GetDimensions(); 00679 00680 int numberOfTuples = dimensions[0]*dimensions[1]*dimensions[2] /3; 00681 this->ImageReslice->GetOutput()->SetScalarTypeToDouble(); 00682 double *scalarPointer = (double*)this->ImageReslice->GetOutput()->GetScalarPointer(); 00683 vtkPoints *vtkpoints = vtkPoints::New(); 00684 vtkpoints->SetNumberOfPoints(numberOfTuples); 00685 //vtkpoints->SetNumberOfPoints(7); 00686 vtkCellArray *vertices = vtkCellArray::New(); 00687 vtkIdType pid; 00688 00689 00690 vtkDoubleArray *dataArray = vtkDoubleArray::New(); 00691 dataArray->SetNumberOfComponents(3); 00692 dataArray->Allocate(numberOfTuples); 00693 dataArray->SetName("Momentum"); 00694 00695 vtkDoubleArray *dataArrayTwo = vtkDoubleArray::New(); 00696 dataArrayTwo->SetNumberOfComponents(1); 00697 dataArrayTwo->Allocate(numberOfTuples); 00698 dataArrayTwo->SetName("default"); 00699 00700 vtkDoubleArray *dataArrayThree = vtkDoubleArray::New(); 00701 dataArrayThree->SetNumberOfComponents(3); 00702 dataArrayThree->Allocate(numberOfTuples); 00703 00704 00705 int numberOfComponents = 3; 00706 double *ptrThree = dataArrayThree->WritePointer(0,numberOfTuples*numberOfComponents); 00707 00708 int dim0,dim1,dim2; 00709 dim0=dim1=dim2=0; 00710 00711 00712 00713 for (int i=0; i<numberOfTuples; i = i++) { 00714 for (int j=0; j<numberOfComponents; j++) { 00715 dim0+=50; 00716 if(dim0 > dimensions[0]*50) { 00717 dim0 = 0; 00718 dim1+=50; 00719 } 00720 if(dim1 >dimensions[1]*50) { 00721 dim1 = 0; 00722 dim2+=50; 00723 } 00724 if(dim2 > dimensions[2]*50) { 00725 dim2 = 0; 00726 } 00727 if(j == 0) { 00728 *ptrThree = dim0; 00729 } 00730 else if(j == 1) { 00731 *ptrThree = dim1; 00732 } 00733 else { 00734 *ptrThree = dim2; 00735 } 00736 ptrThree++; 00737 } 00738 } 00739 00740 00741 vtkpoints->SetData(dataArrayThree); 00742 00743 00744 numberOfComponents = 3; 00745 double *ptr = dataArray->WritePointer(0,numberOfTuples*numberOfComponents); 00746 for (int i=0; i<numberOfTuples; i = i++) { 00747 for (int j=0; j<numberOfComponents; j++) { 00748 *ptr = scalarPointer[(i*numberOfComponents)+j]; 00749 ptr++; 00750 } 00751 } 00752 00753 numberOfComponents = 1; 00754 double *ptrTwo = dataArrayTwo->WritePointer(0,numberOfTuples*numberOfComponents); 00755 for (int i=0; i<numberOfTuples; i = i++) { 00756 for (int j=0; j<numberOfComponents; j++) { 00757 //*ptrTwo = scalarPointer[(i*numberOfComponents)+j]; 00758 //*ptrTwo = cellScalars[(i*numberOfComponents)+j]; 00759 *ptrTwo = 1; 00760 ptrTwo++; 00761 } 00762 } 00763 00764 pd->SetPoints(vtkpoints); 00765 //pd->InsertNextCell(vertex->GetCellType(),vertex->GetPointIds()); 00766 vtkDataSetAttributes *a = pd->GetPointData(); 00767 a->SetVectors(dataArray); 00768 vtkDataSetAttributes *a2=pd->GetCellData(); 00769 a2->SetScalars(dataArrayTwo); 00770 //pd->SetVerts(vertices); 00771 00772 vtkArrowSource* as = vtkArrowSource::New(); 00773 //vtkGlyph3D* gl = vtkGlyph3D::New(); 00774 vtkGlyph2D* gl = vtkGlyph2D::New(); 00775 gl->SetInput(pd); 00776 gl->SetSource(as->GetOutput()); 00777 gl->SetScaleModeToScaleByVector(); 00778 //gl->SetColorModeToColorByVector(); 00779 gl->SetScaleFactor(0.1); 00780 00781 gl->Update(); 00782 00783 //double range[] = {0,0}; 00784 00785 //gl->GetOutput()->GetPointData()->GetScalars()->GetRange(range,2); 00786 00787 vtkLookupTable* lu = vtkLookupTable::New(); 00788 lu->SetNumberOfTableValues(256); 00789 lu->SetHueRange(0.6667, 0); 00790 //lu->SetTableRange(range); 00791 lu->SetVectorMode(vtkScalarsToColors::COMPONENT); 00792 lu->Build(); 00793 this->GetWindowLevel()->SetLookupTable(lu); 00794 00795 //vtkLookupTable *temp = vtkLookupTableManager::GetLookupTable(2); 00796 //temp->SetVectorModeToMagnitude(); 00797 //temp->SetRange(range); 00798 //temp->Build(); 00799 //this->SetLookupTable(temp); 00800 00801 vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); 00802 mapper->SetInputConnection(gl->GetOutputPort()); 00803 mapper->SetLookupTable(lu); 00804 //mapper->SetLookupTable(temp); 00805 //mapper->SelectColorArray("Momentum"); 00806 //mapper->SetUseLookupTableScalarRange(1); 00807 mapper->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA); 00808 gl->Update(); 00809 m_vectorActor->SetMapper(mapper); 00810 00811 this->AddActor(m_vectorActor); 00812 00813 // Save the camera focal and position, and zoom, before calling InternalUpdate() 00814 double focal[3], pos[3], zoom; 00815 this->GetCameraFocalAndPosition (focal, pos); 00816 zoom = this->GetZoom(); 00817 00818 00819 this->SetupAnnotations(); 00820 this->InternalUpdate(); 00821 00822 00823 // Check that the current displayed point lies within the bounds of the image. If not, 00824 // we camp it to the nearest acceptable position. 00825 double *wextent = image->GetBounds(); 00826 double position[3]; 00827 this->GetCurrentPoint ( position ); 00828 position[0]<wextent[0]?position[0]=wextent[0]:position[0]; 00829 position[0]>wextent[1]?position[0]=wextent[1]:position[0]; 00830 position[1]<wextent[2]?position[1]=wextent[2]:position[1]; 00831 position[1]>wextent[3]?position[1]=wextent[3]:position[1]; 00832 position[2]<wextent[4]?position[2]=wextent[4]:position[2]; 00833 position[2]>wextent[5]?position[2]=wextent[5]:position[2]; 00834 this->SetCurrentPoint ( position ); 00835 00836 00837 // restore the zoom and focal in case this is not the first time we render the image. 00838 if( !this->GetFirstImage() ) 00839 { 00840 this->SetZoom ( zoom ); 00841 this->SetCameraFocalAndPosition (focal, pos); 00842 this->SetFirstImage (0); 00843 } 00844 00845 if( this->RulerWidgetVisibility ) 00846 this->RulerWidget->On(); 00847 00848 } 00849 } 00850 00851 void VectorField::SetLookupTable (vtkScalarsToColors* lut) 00852 { 00853 00854 if( !lut ) 00855 { 00856 return; 00857 } 00858 00859 NIREPvtkViewImage::SetLookupTable (lut); 00860 00861 double v_min = this->GetLevel() - 0.5*this->GetWindow(); 00862 double v_max = this->GetLevel() + 0.5*this->GetWindow(); 00863 00869 lut->SetRange ( (v_min-0.5*this->GetShift())/this->GetScale(), 00870 (v_max-1.5*this->GetShift())/this->GetScale() ); 00871 00872 00873 vtkLookupTable* realLut = vtkLookupTable::SafeDownCast (lut); 00874 00875 if( !realLut ) 00876 { 00877 std::cerr << "Error: Cannot cast vtkScalarsToColors to vtkLookupTable." << std::endl; 00878 return; 00879 } 00880 00885 vtkLookupTable* newLut = vtkLookupTable::New(); 00886 newLut->DeepCopy (realLut); 00887 newLut->SetRange (v_min, v_max); 00888 this->WindowLevel->SetLookupTable (newLut); 00889 newLut->Delete(); 00890 00891 } 00892 00893 00894 void VectorField::SetOrientation(unsigned int p_orientation) 00895 { 00896 if( (p_orientation > vtkViewImage::NB_PLAN_IDS - 1) || (this->Orientation == p_orientation) ) 00897 { 00898 return; 00899 } 00900 00901 this->Orientation = p_orientation; 00902 00903 00904 // setup the OrientationMatrix and the ScreenToRealWorldMatrix. Then, we have no 00905 // need to check the view's orientation to determine what slice to display: a 00906 // simple matrix multiplication will tell it for us. 00907 this->OrientationMatrix->Zero(); 00908 this->ScreenToRealWorldMatrix->Zero(); 00909 00910 00911 if( this->Orientation == vtkViewImage::SAGITTAL_ID ) 00912 { 00913 this->ImageReslice->SetResliceAxesDirectionCosines( 0, -1, 0, 00914 0, 0, 1, 00915 1, 0, 0); 00916 this->OrientationMatrix->SetElement (0, 2, 0.0); 00917 this->OrientationMatrix->SetElement (1, 0, -1.0); 00918 this->OrientationMatrix->SetElement (2, 1, 1.0); 00919 00920 this->ScreenToRealWorldMatrix->SetElement (0, 0, 1.0); 00921 } 00922 00923 00924 if( this->Orientation == vtkViewImage::CORONAL_ID ) 00925 { 00926 if( this->Conventions == RADIOLOGIC ) 00927 { 00928 this->OrientationMatrix->SetElement(0, 0, 1.0); 00929 this->ImageReslice->SetResliceAxesDirectionCosines(1, 0, 0, 00930 0, 0, 1, 00931 0, 1, 0); 00932 } 00933 else 00934 { 00935 this->OrientationMatrix->SetElement(0, 0, -1.0); 00936 this->ImageReslice->SetResliceAxesDirectionCosines(-1, 0, 0, 00937 0, 0, 1, 00938 0, 1, 0); 00939 } 00940 00941 this->OrientationMatrix->SetElement(2, 1, 1.0); 00942 this->ScreenToRealWorldMatrix->SetElement (1, 1, 1.0); 00943 } 00944 00945 00946 if( this->Orientation == vtkViewImage::AXIAL_ID ) 00947 { 00948 00949 00950 if( this->Conventions == RADIOLOGIC ) 00951 { 00952 this->OrientationMatrix->SetElement(0, 0, 1.0 ); 00953 this->ImageReslice->SetResliceAxesDirectionCosines(1, 0, 0, 00954 0, 1, 0, 00955 0, 0, 1); 00956 } 00957 else 00958 { 00959 this->OrientationMatrix->SetElement(0, 0, -1.0 ); 00960 this->ImageReslice->SetResliceAxesDirectionCosines(-1, 0, 0, 00961 0, 1, 0, 00962 0, 0, 1); 00963 } 00964 00965 this->OrientationMatrix->SetElement(1, 1, 1.0 ); 00966 this->ScreenToRealWorldMatrix->SetElement (2, 2, 1.0); 00967 } 00968 00969 unsigned int direction = this->GetOrthogonalAxis (this->GetOrientation()); 00970 switch(direction) 00971 { 00972 case X_ID : 00973 this->DataSetCutPlane->SetNormal (1,0,0); 00974 break; 00975 case Y_ID : 00976 this->DataSetCutPlane->SetNormal (0,1,0); 00977 break; 00978 case Z_ID : 00979 this->DataSetCutPlane->SetNormal (0,0,1); 00980 break; 00981 } 00982 00983 //this->ImageReslice->Modified(); 00984 00985 this->UpdateImageActor(); // make sure update extent are up to date 00986 this->UpdatePosition(); // make sure reslicer origin are ok 00987 this->InitializeImagePositionAndSize(); // reset and center the view 00988 this->SetupAnnotations(); // make sure annotations are ok 00989 00990 this->Modified(); 00991 00992 } 00993 00994 00995 00996 vtkActor* VectorField::AddDataSet (vtkDataSet* dataset, vtkProperty* property) 00997 { 00998 00999 bool doit = true; 01000 01001 if (!dataset) 01002 doit = false; 01003 01004 if( this->HasDataSet (dataset) ) 01005 { 01006 doit = false; 01007 } 01008 vtkImageData* imagedata = NULL; 01009 imagedata = vtkImageData::SafeDownCast(dataset); 01010 01011 if (imagedata) 01012 { 01013 this->SetImage(imagedata); 01014 } 01015 else 01016 { 01017 01018 if ( !this->GetImage() ) 01019 { 01020 doit = false; 01021 } 01022 // don't constrain the memory of input datasets anymore. 01033 if (doit) 01034 { 01035 01036 vtkMatrix4x4* matrix = vtkMatrix4x4::New(); 01037 for (unsigned int i=0; i<3; i++) 01038 { 01039 for (unsigned int j=0; j<3; j++) 01040 { 01041 matrix->SetElement(i,j,this->ImageReslice->GetResliceAxes()->GetElement(j,i)); 01042 } 01043 matrix->SetElement(i,3,0); 01044 } 01045 matrix->SetElement(3,3,1); 01046 01047 vtkCutter* cutter = vtkCutter::New(); 01048 cutter->SetCutFunction (this->DataSetCutPlane); 01049 01050 // Very strangely in some cases (ex : landmarks) 01051 // the cutter increments the RefCount of the input dataset by 2 01052 // making some memory leek... 01053 // I could not manage to know what is wrong here 01054 01055 cutter->SetInput (dataset); 01056 cutter->Update(); 01057 01058 if (!cutter->GetOutput()) 01059 { 01060 vtkWarningMacro(<< "Unable to cut this dataset..."); 01061 matrix->Delete(); 01062 cutter->Delete(); 01063 return NULL; 01064 } 01065 01066 01067 vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); 01068 mapper->SetInput (cutter->GetOutput()); 01069 01070 vtkActor* actor = vtkActor::New(); 01071 actor->SetUserMatrix (matrix); 01072 actor->SetMapper (mapper); 01073 if (property) 01074 { 01075 actor->SetProperty (property); 01076 } 01077 01078 actor->PickableOff(); 01079 01080 this->AddActor (actor); 01081 this->DataSetList.push_back (dataset); 01082 this->DataSetActorList.push_back (actor); 01083 01084 this->ResetAndRestablishZoomAndCamera(); 01085 01086 actor->Delete(); 01087 mapper->Delete(); 01088 matrix->Delete(); 01089 cutter->Delete(); 01090 } 01091 } 01092 01093 01094 return this->GetDataSetActor(dataset); 01095 01096 } 01097 01098 01104 vtkActor* VectorField::SyncAddPolyData (vtkPolyData* polydata, vtkProperty* property, double thickness) 01105 { 01106 01107 if( this->IsLocked() ) 01108 { 01109 return NULL; 01110 } 01111 01112 01113 vtkActor* actor = this->AddPolyData (polydata, property, thickness); 01114 01115 this->Lock(); 01116 for( unsigned int i=0; i<this->Children.size(); i++) 01117 { 01118 // VectorField* view = dynamic_cast<VectorField*> (this->Children[i]); 01119 VectorField* view = VectorField::SafeDownCast (this->Children[i]); 01120 if( view ) 01121 { 01122 view->SyncAddPolyData (polydata, property, thickness); 01123 } 01124 } 01125 this->UnLock(); 01126 01127 return actor; 01128 01129 01130 } 01131 01132