Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkRegEvaluationMapper2D.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 //MITK
19 #include <mitkDataNode.h>
20 #include <mitkImageSliceSelector.h>
23 #include <mitkPlaneGeometry.h>
24 #include <mitkProperties.h>
27 #include <mitkPixelType.h>
30 #include "mitkPlaneClipping.h"
31 
32 #include "mitkRegVisPropertyTags.h"
33 #include "mitkRegVisHelper.h"
36 
37 //MITK Rendering
42 
43 //VTK
44 #include <vtkProperty.h>
45 #include <vtkTransform.h>
46 #include <vtkMatrix4x4.h>
47 #include <vtkLookupTable.h>
48 #include <vtkImageData.h>
49 #include <vtkPoints.h>
50 #include <vtkGeneralTransform.h>
51 #include <vtkImageExtractComponents.h>
52 #include <vtkImageReslice.h>
53 #include <vtkImageChangeInformation.h>
54 #include <vtkPlaneSource.h>
55 #include <vtkPolyDataMapper.h>
56 #include <vtkCellArray.h>
57 #include <vtkCamera.h>
58 #include <vtkColorTransferFunction.h>
59 #include <vtkImageCheckerboard.h>
60 #include <vtkImageWeightedSum.h>
61 #include <vtkImageMathematics.h>
62 #include <vtkImageRectilinearWipe.h>
63 #include <vtkImageGradientMagnitude.h>
64 #include <vtkImageAppendComponents.h>
65 #include <vtkImageExtractComponents.h>
66 
67 //ITK
68 #include <itkRGBAPixel.h>
70 
71 //MatchPoint
73 #include <mitkImageMappingHelper.h>
74 
76 {
77 }
78 
80 {
81 }
82 
83 //set the two points defining the textured plane according to the dimension and spacing
84 void mitk::RegEvaluationMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6])
85 {
86  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
87 
88  float depth = this->CalculateLayerDepth(renderer);
89  //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct
90  //plane size in crosshair rotation and swivel mode.
91  localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth);
92  //These two points define the axes of the plane in combination with the origin.
93  //Point 1 is the x-axis and point 2 the y-axis.
94  //Each plane is transformed according to the view (axial, coronal and saggital) afterwards.
95  localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth)
96  localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth)
97 }
98 
100 {
101  //get the clipping range to check how deep into z direction we can render images
102  double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1];
103 
104  //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined
105  float depth = -maxRange*0.01; // divide by 100
106  int layer = 0;
107  GetDataNode()->GetIntProperty( "layer", layer, renderer);
108  //add the layer property for each image to render images with a higher layer on top of the others
109  depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between)
110  if(depth > 0.0f) {
111  depth = 0.0f;
112  MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead.";
113  }
114  return depth;
115 }
116 
118 {
119  const mitk::RegEvaluationObject* evalObj = dynamic_cast< const mitk::RegEvaluationObject* >( GetDataNode()->GetData() );
120  if (evalObj)
121  {
122  return evalObj->GetTargetImage();
123  }
124 
125  return NULL;
126 }
127 
129 {
130  const mitk::RegEvaluationObject* evalObj = dynamic_cast< const mitk::RegEvaluationObject* >( GetDataNode()->GetData() );
131  if (evalObj)
132  {
133  return evalObj->GetMovingImage();
134  }
135 
136  return NULL;
137 }
138 
140 {
141  const mitk::RegEvaluationObject* evalObj = dynamic_cast< const mitk::RegEvaluationObject* >(GetDataNode()->GetData());
142  if (evalObj)
143  {
144  return evalObj->GetTargetNode();
145  }
146 
147  return NULL;
148 }
149 
151 {
152  const mitk::RegEvaluationObject* evalObj = dynamic_cast< const mitk::RegEvaluationObject* >(GetDataNode()->GetData());
153  if (evalObj)
154  {
155  return evalObj->GetMovingNode();
156  }
157 
158  return NULL;
159 }
160 
162 {
163  const mitk::RegEvaluationObject* evalObj = dynamic_cast< const mitk::RegEvaluationObject* >( GetDataNode()->GetData() );
164  if (evalObj)
165  {
166  return evalObj->GetRegistration();
167  }
168 
169  return NULL;
170 }
171 
173 {
174  //return the actor corresponding to the renderer
175  return m_LSH.GetLocalStorage(renderer)->m_Actors;
176 }
177 
179 {
180  bool updated = false;
181  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
182 
183  mitk::Image::Pointer targetInput = const_cast< mitk::Image * >( this->GetTargetImage() );
184  mitk::DataNode* datanode = this->GetDataNode();
185 
186  if ( targetInput.IsNull() || targetInput->IsInitialized() == false )
187  {
188  return;
189  }
190 
191  mitk::Image::ConstPointer movingInput = this->GetMovingImage();
192 
193  if ( movingInput.IsNull() || movingInput->IsInitialized() == false )
194  {
195  return;
196  }
197 
198  mitk::MAPRegistrationWrapper::ConstPointer reg = this->GetRegistration();
199 
200  //check if there is a valid worldGeometry
201  const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D();
202  if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() ))
203  {
204  return;
205  }
206 
207  if(targetInput->GetMTime()>localStorage->m_LastUpdateTime
208  || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified?
209  || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()))
210  { //target input has been modified -> reslice target input
211  targetInput->Update();
212 
213  // early out if there is no intersection of the current rendering geometry
214  // and the geometry of the image that is to be rendered.
215  if ( !RenderingGeometryIntersectsImage( worldGeometry, targetInput->GetSlicedGeometry() ) )
216  {
217  // set image to NULL, to clear the texture in 3D, because
218  // the latest image is used there if the plane is out of the geometry
219  // see bug-13275
220  localStorage->m_EvaluationImage = NULL;
221  localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData );
222  return;
223  }
224 
225  //set main input for ExtractSliceFilter
226  localStorage->m_Reslicer->SetInput(targetInput);
227  localStorage->m_Reslicer->SetWorldGeometry(worldGeometry);
228  localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() );
229 
230 
231  //set the transformation of the image to adapt reslice axis
232  localStorage->m_Reslicer->SetResliceTransformByGeometry( targetInput->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) );
233 
234 
235  //is the geometry of the slice based on the input image or the worldgeometry?
236  bool inPlaneResampleExtentByGeometry = false;
237  datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer);
238  localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry);
239 
240 
241  // Initialize the interpolation mode for resampling; switch to nearest
242  // neighbor if the input image is too small.
243  if ( (targetInput->GetDimension() >= 3) && (targetInput->GetDimension(2) > 1) )
244  {
245  VtkResliceInterpolationProperty *resliceInterpolationProperty;
246  datanode->GetProperty(
247  resliceInterpolationProperty, "reslice interpolation" );
248 
249  int interpolationMode = VTK_RESLICE_NEAREST;
250  if ( resliceInterpolationProperty != NULL )
251  {
252  interpolationMode = resliceInterpolationProperty->GetInterpolation();
253  }
254 
255  switch ( interpolationMode )
256  {
257  case VTK_RESLICE_NEAREST:
258  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
259  break;
260  case VTK_RESLICE_LINEAR:
261  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR);
262  break;
263  case VTK_RESLICE_CUBIC:
264  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC);
265  break;
266  }
267  }
268  else
269  {
270  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
271  }
272 
273  //this is needed when thick mode was enable bevore. These variable have to be reset to default values
274  localStorage->m_Reslicer->SetOutputDimensionality( 2 );
275  localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0);
276  localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 );
277 
278  localStorage->m_Reslicer->Modified();
279  //start the pipeline with updating the largest possible, needed if the geometry of the input has changed
280  localStorage->m_Reslicer->UpdateLargestPossibleRegion();
281  localStorage->m_slicedTargetImage = localStorage->m_Reslicer->GetOutput();
282  updated = true;
283  }
284 
285  if(updated ||
286  movingInput->GetMTime() > localStorage->m_LastUpdateTime ||
287  reg->GetMTime() > localStorage->m_LastUpdateTime)
288  {
289  //Map moving image
290  localStorage->m_slicedMappedImage = mitk::ImageMappingHelper::map(movingInput,reg,false,0,localStorage->m_slicedTargetImage->GetGeometry(),false,0);
291  updated = true;
292  }
293 
294  // Bounds information for reslicing (only required if reference geometry
295  // is present)
296  //this used for generating a vtkPLaneSource with the right size
297  double sliceBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
298 
299  if (updated
300  || (localStorage->m_LastUpdateTime < datanode->GetPropertyList()->GetMTime()) //was a property modified?
301  || (localStorage->m_LastUpdateTime < datanode->GetPropertyList(renderer)->GetMTime())
302  || (localStorage->m_LastUpdateTime < this->GetTargetNode()->GetMTime())
303  || (localStorage->m_LastUpdateTime < this->GetMovingNode()->GetMTime()))
304  {
305  localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds);
306 
307  //get the spacing of the slice
308  localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing();
309 
310  // calculate minimum bounding rect of IMAGE in texture
311  {
312  double textureClippingBounds[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
313 
314  // Calculate the actual bounds of the transformed plane clipped by the
315  // dataset bounding box; this is required for drawing the texture at the
316  // correct position during 3D mapping.
317 
318  const PlaneGeometry *planeGeometry = dynamic_cast<const PlaneGeometry *>(worldGeometry);
319  mitk::PlaneClipping::CalculateClippedPlaneBounds(targetInput->GetGeometry(), planeGeometry, textureClippingBounds);
320 
321  textureClippingBounds[0] = static_cast<int>(textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5);
322  textureClippingBounds[1] = static_cast<int>(textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5);
323  textureClippingBounds[2] = static_cast<int>(textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5);
324  textureClippingBounds[3] = static_cast<int>(textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5);
325 
326  //clipping bounds for cutting the image
327  localStorage->m_TargetLevelWindowFilter->SetClippingBounds(textureClippingBounds);
328  localStorage->m_MappedLevelWindowFilter->SetClippingBounds(textureClippingBounds);
329  }
330 
331  this->ApplyLookuptable(renderer, this->GetTargetNode(), localStorage->m_TargetLevelWindowFilter);
332  this->ApplyLookuptable(renderer, this->GetMovingNode(), localStorage->m_MappedLevelWindowFilter);
333  this->ApplyLevelWindow(renderer, this->GetTargetNode(), localStorage->m_TargetLevelWindowFilter);
334  this->ApplyLevelWindow(renderer, this->GetMovingNode(), localStorage->m_MappedLevelWindowFilter);
335 
336  //connect the input with the levelwindow filter
337  localStorage->m_TargetLevelWindowFilter->SetInputData(localStorage->m_slicedTargetImage->GetVtkImageData());
338  localStorage->m_MappedLevelWindowFilter->SetInputData(localStorage->m_slicedMappedImage->GetVtkImageData());
339 
340  localStorage->m_TargetExtractFilter->SetInputConnection(localStorage->m_TargetLevelWindowFilter->GetOutputPort());
341  localStorage->m_MappedExtractFilter->SetInputConnection(localStorage->m_MappedLevelWindowFilter->GetOutputPort());
342  localStorage->m_TargetExtractFilter->SetComponents(0);
343  localStorage->m_MappedExtractFilter->SetComponents(0);
344 
345  updated = true;
346  }
347 
348  //Generate evaluation image
349  bool isStyleOutdated = mitk::PropertyIsOutdated(datanode,mitk::nodeProp_RegEvalStyle,localStorage->m_LastUpdateTime);
350  bool isBlendOutdated = mitk::PropertyIsOutdated(datanode,mitk::nodeProp_RegEvalBlendFactor,localStorage->m_LastUpdateTime);
351  bool isCheckerOutdated = mitk::PropertyIsOutdated(datanode,mitk::nodeProp_RegEvalCheckerCount,localStorage->m_LastUpdateTime);
352  bool isWipeStyleOutdated = mitk::PropertyIsOutdated(datanode,mitk::nodeProp_RegEvalWipeStyle,localStorage->m_LastUpdateTime);
353  bool isContourOutdated = mitk::PropertyIsOutdated(datanode,mitk::nodeProp_RegEvalTargetContour,localStorage->m_LastUpdateTime);
354  bool isPositionOutdated = mitk::PropertyIsOutdated(datanode, mitk::nodeProp_RegEvalCurrentPosition, localStorage->m_LastUpdateTime);
355 
356  if (updated ||
357  isStyleOutdated ||
358  isBlendOutdated ||
359  isCheckerOutdated ||
360  isWipeStyleOutdated ||
361  isContourOutdated ||
362  isPositionOutdated)
363  {
365  datanode->GetProperty(evalStyleProp, mitk::nodeProp_RegEvalStyle);
366 
367  switch (evalStyleProp->GetValueAsId())
368  {
369  case 0 :
370  {
371  PrepareBlend(datanode, localStorage);
372  break;
373  }
374  case 1 :
375  {
376  PrepareColorBlend(localStorage);
377  break;
378  }
379  case 2 :
380  {
381  PrepareCheckerBoard(datanode, localStorage);
382  break;
383  }
384  case 3 :
385  {
386  const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldGeometry2D();
387 
388  Point3D currentPos3D;
390 
391  Point2D currentPos2D;
392  worldGeometry->Map(currentPos3D, currentPos2D);
393  Point2D currentIndex2D;
394  worldGeometry->WorldToIndex(currentPos2D, currentIndex2D);
395 
396  PrepareWipe(datanode, localStorage, currentIndex2D);
397  break;
398  }
399  case 4 :
400  {
401  PrepareDifference(localStorage);
402  break;
403  }
404  case 5 :
405  {
406  PrepareContour(datanode, localStorage);
407  break;
408  }
409  }
410  updated = true;
411  }
412 
413  if(updated
414  || (localStorage->m_LastUpdateTime < datanode->GetPropertyList()->GetMTime()) //was a property modified?
415  || (localStorage->m_LastUpdateTime < datanode->GetPropertyList(renderer)->GetMTime()) )
416  {
417  this->ApplyOpacity( renderer );
418 
419  // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
420  localStorage->m_Texture->MapColorScalarsThroughLookupTableOff();
421 
422  // check for texture interpolation property
423  bool textureInterpolation = false;
424  GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer );
425 
426  //set the interpolation modus according to the property
427  localStorage->m_Texture->SetInterpolate(textureInterpolation);
428 
429  // connect the texture with the output of the levelwindow filter
430  localStorage->m_Texture->SetInputData(localStorage->m_EvaluationImage);
431 
432  this->TransformActor( renderer );
433 
434  vtkActor* contourShadowActor = dynamic_cast<vtkActor*> (localStorage->m_Actors->GetParts()->GetItemAsObject(0));
435 
436  //Connect the mapper with the input texture. This is the standard case.
437  //setup the textured plane
438  this->GeneratePlane( renderer, sliceBounds );
439  //set the plane as input for the mapper
440  localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort());
441  //set the texture for the actor
442 
443  localStorage->m_Actor->SetTexture(localStorage->m_Texture);
444  contourShadowActor->SetVisibility( false );
445 
446  // We have been modified => save this for next Update()
447  localStorage->m_LastUpdateTime.Modified();
448  }
449 }
450 
451 
453 {
454  bool targetContour = true;
455  datanode->GetBoolProperty(mitk::nodeProp_RegEvalTargetContour,targetContour);
456 
457  vtkSmartPointer<vtkImageGradientMagnitude> magFilter =
459 
460  if(targetContour)
461  {
462  magFilter->SetInputConnection(localStorage->m_TargetExtractFilter->GetOutputPort());
463  }
464  else
465  {
466  magFilter->SetInputConnection(localStorage->m_MappedExtractFilter->GetOutputPort());
467  }
468 
469  vtkSmartPointer<vtkImageAppendComponents> appendFilter =
471 
472  appendFilter->AddInputConnection(magFilter->GetOutputPort());
473  appendFilter->AddInputConnection(magFilter->GetOutputPort());
474  if(targetContour)
475  {
476  appendFilter->AddInputConnection(localStorage->m_MappedExtractFilter->GetOutputPort());
477  }
478  else
479  {
480  appendFilter->AddInputConnection(localStorage->m_TargetExtractFilter->GetOutputPort());
481  }
482  appendFilter->Update();
483 
484  localStorage->m_EvaluationImage = appendFilter->GetOutput();
485 }
486 
488 {
489  vtkSmartPointer<vtkImageMathematics> diffFilter =
491  vtkSmartPointer<vtkImageMathematics> minFilter =
493  vtkSmartPointer<vtkImageMathematics> maxFilter =
495 
496  minFilter->SetInputConnection(0, localStorage->m_TargetExtractFilter->GetOutputPort());
497  minFilter->SetInputConnection(1, localStorage->m_MappedExtractFilter->GetOutputPort());
498  minFilter->SetOperationToMin();
499  maxFilter->SetInputConnection(0, localStorage->m_TargetExtractFilter->GetOutputPort());
500  maxFilter->SetInputConnection(1, localStorage->m_MappedExtractFilter->GetOutputPort());
501  maxFilter->SetOperationToMax();
502 
503  diffFilter->SetInputConnection(0, maxFilter->GetOutputPort());
504  diffFilter->SetInputConnection(1, minFilter->GetOutputPort());
505  diffFilter->SetOperationToSubtract();
506  diffFilter->Update();
507  localStorage->m_EvaluationImage = diffFilter->GetOutput();
508 }
509 
510 void mitk::RegEvaluationMapper2D::PrepareWipe(mitk::DataNode* datanode, LocalStorage * localStorage, const Point2D& currentIndex2D)
511 {
513  datanode->GetProperty(evalWipeStyleProp, mitk::nodeProp_RegEvalWipeStyle);
514 
515  vtkSmartPointer<vtkImageRectilinearWipe> wipedFilter =
517  wipedFilter->SetInputConnection(0, localStorage->m_TargetLevelWindowFilter->GetOutputPort());
518  wipedFilter->SetInputConnection(1, localStorage->m_MappedLevelWindowFilter->GetOutputPort());
519  wipedFilter->SetPosition(currentIndex2D[0], currentIndex2D[1]);
520 
521  if (evalWipeStyleProp->GetValueAsId() == 0)
522  {
523  wipedFilter->SetWipeToQuad();
524  }
525  else if (evalWipeStyleProp->GetValueAsId() == 1)
526  {
527  wipedFilter->SetWipeToHorizontal();
528  }
529  else if (evalWipeStyleProp->GetValueAsId() == 2)
530  {
531  wipedFilter->SetWipeToVertical();
532  }
533 
534  wipedFilter->Update();
535 
536  localStorage->m_EvaluationImage = wipedFilter->GetOutput();
537 }
538 
540 {
541  int checkerCount = 5;
542  datanode->GetIntProperty(mitk::nodeProp_RegEvalCheckerCount,checkerCount);
543 
544  vtkSmartPointer<vtkImageCheckerboard> checkerboardFilter =
546  checkerboardFilter->SetInputConnection(0, localStorage->m_TargetLevelWindowFilter->GetOutputPort());
547  checkerboardFilter->SetInputConnection(1, localStorage->m_MappedLevelWindowFilter->GetOutputPort());
548  checkerboardFilter->SetNumberOfDivisions(checkerCount, checkerCount, 1);
549  checkerboardFilter->Update();
550 
551  localStorage->m_EvaluationImage = checkerboardFilter->GetOutput();
552 }
553 
555 {
556  vtkSmartPointer<vtkImageAppendComponents> appendFilter =
558 
559  //red channel
560  appendFilter->AddInputConnection(localStorage->m_MappedExtractFilter->GetOutputPort());
561  //green channel
562  appendFilter->AddInputConnection(localStorage->m_MappedExtractFilter->GetOutputPort());
563 
564  //blue channel
565  appendFilter->AddInputConnection(localStorage->m_TargetExtractFilter->GetOutputPort());
566  appendFilter->Update();
567 
568  localStorage->m_EvaluationImage = appendFilter->GetOutput();
569 }
570 
572 {
573  int blendfactor = 50;
574  datanode->GetIntProperty(mitk::nodeProp_RegEvalBlendFactor,blendfactor);
575 
576  vtkSmartPointer<vtkImageWeightedSum> blendFilter =
578 
579  blendFilter->AddInputConnection(localStorage->m_TargetExtractFilter->GetOutputPort());
580  blendFilter->AddInputConnection(localStorage->m_MappedExtractFilter->GetOutputPort());
581  blendFilter->SetWeight(0, (100 - blendfactor) / 100.);
582  blendFilter->SetWeight(1,blendfactor/100.);
583  blendFilter->Update();
584 
585  localStorage->m_EvaluationImage = blendFilter->GetOutput();
586 }
587 
589 {
590  LocalStorage *localStorage = this->GetLocalStorage( renderer );
591 
592  LevelWindow levelWindow;
593  dataNode->GetLevelWindow(levelWindow, renderer, "levelwindow");
594  levelFilter->GetLookupTable()->SetRange(levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound());
595 
596  mitk::LevelWindow opacLevelWindow;
597  if (dataNode->GetLevelWindow(opacLevelWindow, renderer, "opaclevelwindow"))
598  {
599  //pass the opaque level window to the filter
600  levelFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound());
601  levelFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound());
602  }
603  else
604  {
605  //no opaque level window
606  levelFilter->SetMinOpacity(0.0);
607  levelFilter->SetMaxOpacity(255.0);
608  }
609 }
610 
612 {
613  LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer);
614  vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable;
615 
616  // If lookup table or transferfunction use is requested...
617  mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast<mitk::LookupTableProperty*>(dataNode->GetProperty("LookupTable"));
618 
619  if (lookupTableProp.IsNotNull()) // is a lookuptable set?
620  {
621  usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable();
622  }
623  else
624  {
625  //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'.
626  //A default (rainbow) lookup table will be used.
627  //Here have to do nothing. Warning for the user has been removed, due to unwanted console output
628  //in every interation of the rendering.
629  }
630  levelFilter->SetLookupTable(usedLookupTable);
631 }
632 
634 {
635  LocalStorage* localStorage = this->GetLocalStorage( renderer );
636  float opacity = 1.0f;
637  // check for opacity prop and use it for rendering if it exists
638  GetDataNode()->GetOpacity( opacity, renderer, "opacity" );
639  //set the opacity according to the properties
640  localStorage->m_Actor->GetProperty()->SetOpacity(opacity);
641  if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 )
642  {
643  dynamic_cast<vtkActor*>( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity);
644  }
645 }
646 
648 {
649 
650  bool visible = true;
651  GetDataNode()->GetVisibility(visible, renderer, "visible");
652 
653  if ( !visible )
654  {
655  return;
656  }
657 
658  mitk::Image* data = const_cast<mitk::Image *>( this->GetTargetImage() );
659  if ( data == NULL )
660  {
661  return;
662  }
663 
664  // Calculate time step of the input data for the specified renderer (integer value)
665  this->CalculateTimeStep( renderer );
666 
667  // Check if time step is valid
668  const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry();
669  if ( ( dataTimeGeometry == NULL )
670  || ( dataTimeGeometry->CountTimeSteps() == 0 )
671  || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) )
672  {
673  return;
674  }
675 
676  const DataNode *node = this->GetDataNode();
677  data->UpdateOutputInformation();
678  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
679 
680  //check if something important has changed and we need to rerender
681  if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified?
682  || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified?
683  || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified?
684  || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime())
685  || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified?
686  || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())
687  || (localStorage->m_LastUpdateTime < this->GetTargetNode()->GetMTime()) //was the target node modified?
688  || (localStorage->m_LastUpdateTime < this->GetMovingNode()->GetMTime()) //was the moving node modified?
689  || (localStorage->m_LastUpdateTime < this->GetTargetNode()->GetPropertyList()->GetMTime()) //was a target node property modified?
690  || (localStorage->m_LastUpdateTime < this->GetTargetNode()->GetPropertyList(renderer)->GetMTime())
691  || (localStorage->m_LastUpdateTime < this->GetMovingNode()->GetPropertyList()->GetMTime()) //was a moving node property modified?
692  || (localStorage->m_LastUpdateTime < this->GetMovingNode()->GetPropertyList(renderer)->GetMTime()))
693  {
694  this->GenerateDataForRenderer( renderer );
695  }
696 
697  // since we have checked that nothing important has changed, we can set
698  // m_LastUpdateTime to the current time
699  localStorage->m_LastUpdateTime.Modified();
700 }
701 
703 {
704  mitk::RegEvaluationObject* regEval = dynamic_cast<mitk::RegEvaluationObject*>(node->GetData());
705 
706  if(!regEval)
707  {
708  return;
709  }
710 
711  // Properties common for both images and segmentations
712  node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite );
713  if(regEval->GetTargetImage() && regEval->GetTargetImage()->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) );
714  else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() );
715  node->AddProperty( "texture interpolation", mitk::BoolProperty::New( false ) ); // set to user configurable default value (see global options)
716  node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) );
717  node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) );
718 
720  node->AddProperty( "Image Rendering.Mode", renderingModeProperty);
721 
722  // Set default grayscale look-up table
725  mitkLutProp->SetLookupTable(mitkLut);
726  node->SetProperty("LookupTable", mitkLutProp);
727 
728  node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite );
729  node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite );
730  node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite );
731  node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite);
732 
739 
740  Superclass::SetDefaultProperties(node, renderer, overwrite);
741 }
742 
744 {
745  return m_LSH.GetLocalStorage(renderer);
746 }
747 
749 {
750  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
751  //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital
752  vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
753  vtkSmartPointer<vtkMatrix4x4> matrix = localStorage->m_Reslicer->GetResliceAxes();
754  trans->SetMatrix(matrix);
755  //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital)
756  localStorage->m_Actor->SetUserTransform(trans);
757  //transform the origin to center based coordinates, because MITK is center based.
758  localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0);
759 
760  if ( localStorage->m_Actors->GetNumberOfPaths() > 1 )
761  {
762  vtkActor* secondaryActor = dynamic_cast<vtkActor*>( localStorage->m_Actors->GetParts()->GetItemAsObject(0) );
763  secondaryActor->SetUserTransform(trans);
764  secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0);
765  }
766 }
767 
769 {
770  // if either one of the two geometries is NULL we return true
771  // for safety reasons
772  if ( renderingGeometry == NULL || imageGeometry == NULL )
773  return true;
774 
775  // get the distance for the first cornerpoint
776  ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) );
777  for( int i=1; i<8; i++ )
778  {
779  mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i );
780 
781  // get the distance to the other cornerpoints
782  ScalarType distance = renderingGeometry->SignedDistance( cornerPoint );
783 
784  // if it has not the same signing as the distance of the first point
785  if ( initialDistance * distance < 0 )
786  {
787  // we have an intersection and return true
788  return true;
789  }
790  }
791 
792  // all distances have the same sign, no intersection and we return false
793  return false;
794 }
795 
797 {
798 }
799 
801 {
802  m_TargetLevelWindowFilter = vtkSmartPointer<vtkMitkLevelWindowFilter>::New();
803  m_MappedLevelWindowFilter = vtkSmartPointer<vtkMitkLevelWindowFilter>::New();
804 
805  m_TargetExtractFilter = vtkSmartPointer<vtkImageExtractComponents>::New();
806  m_MappedExtractFilter = vtkSmartPointer<vtkImageExtractComponents>::New();
807 
808 
809 
810  //Do as much actions as possible in here to avoid double executions.
812  //m_Texture = vtkSmartPointer<vtkNeverTranslucentTexture>::New().GetPointer();
813  m_Texture = vtkSmartPointer<vtkOpenGLTexture>::New().GetPointer();
814  m_DefaultLookupTable = vtkSmartPointer<vtkLookupTable>::New();
815  m_ColorLookupTable = vtkSmartPointer<vtkLookupTable>::New();
817  m_Actor = vtkSmartPointer<vtkActor>::New();
819  m_Reslicer = mitk::ExtractSliceFilter::New();
820  m_EvaluationImage = vtkSmartPointer<vtkImageData>::New();
821  m_EmptyPolyData = vtkSmartPointer<vtkPolyData>::New();
822 
824  //built a default lookuptable
825  mitkLUT->SetType(mitk::LookupTable::GRAYSCALE);
826  m_DefaultLookupTable = mitkLUT->GetVtkLookupTable();
827 
828  mitkLUT->SetType(mitk::LookupTable::JET);
829  m_ColorLookupTable = mitkLUT->GetVtkLookupTable();
830 
831  //do not repeat the texture (the image)
832  m_Texture->RepeatOff();
833 
834  //set the mapper for the actor
835  m_Actor->SetMapper( m_Mapper );
836 
837  vtkSmartPointer<vtkActor> outlineShadowActor = vtkSmartPointer<vtkActor>::New();
838  outlineShadowActor->SetMapper( m_Mapper );
839 
840  m_Actors->AddPart( outlineShadowActor );
841  m_Actors->AddPart( m_Actor );
842 }
vtkSmartPointer< vtkMitkLevelWindowFilter > m_MappedLevelWindowFilter
This filter is used to apply the level window to moving image.
vtkSmartPointer< vtkImageData > m_EvaluationImage
Current slice of a 2D render window.
void ApplyLookuptable(mitk::BaseRenderer *renderer, const mitk::DataNode *dataNode, vtkMitkLevelWindowFilter *levelFilter)
This method applies (or modifies) the lookuptable for all types of images.
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is NULL, the BaseRenderer-independent PropertyList ...
mitk::ScalarType * m_mmPerPixel
mmPerPixel relation between pixel and mm. (World spacing).
ScalarType GetLowerWindowBound() const
virtual vtkProp * GetVtkProp(mitk::BaseRenderer *renderer)
vtkSmartPointer< vtkMitkLevelWindowFilter > m_TargetLevelWindowFilter
This filter is used to apply the level window to target image.
vtkSmartPointer< vtkPlaneSource > m_Plane
Plane on which the slice is rendered as texture.
virtual unsigned long GetMTime() const override
Get the timestamp of the last change of the map or the last change of one of the properties store in ...
float CalculateLayerDepth(mitk::BaseRenderer *renderer)
This method uses the vtkCamera clipping range and the layer property to calcualte the depth of the ob...
bool RenderingGeometryIntersectsImage(const Geometry2D *renderingGeometry, SlicedGeometry3D *imageGeometry)
Calculates whether the given rendering geometry intersects the given SlicedGeometry3D.
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
virtual mitk::Image * GetMovingImage()
void PrepareColorBlend(LocalStorage *localStorage)
virtual bool IsValid() const
Is this BaseGeometry in a state that is valid?
virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer)
Does the actual resampling, without rendering the image yet. All the data is generated inside this me...
void GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6])
Generates a plane according to the size of the resliced image in milimeters.
double ScalarType
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
virtual const mitk::DataNode * GetTargetNode()
static bool CalculateClippedPlaneBounds(const BaseGeometry *boundingGeometry, const PlaneGeometry *planeGeometry, double *bounds)
Calculate the bounding box of the resliced image. This is necessary for arbitrarily rotated planes in...
vtkSmartPointer< vtkImageExtractComponents > m_MappedExtractFilter
static Pointer New()
Organizes the rendering process.
virtual ScalarType SignedDistance(const Point3D &pt3d_mm) const
bool GetBoolProperty(const char *propertyKey, bool &boolValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for bool properties (instances of BoolProperty)
void PrepareBlend(mitk::DataNode *datanode, LocalStorage *localStorage)
const char *const nodeProp_RegEvalCheckerCount
virtual mitk::MAPRegistrationWrapper * GetRegistration()
void SetLookupTable(vtkScalarsToColors *lookupTable)
Set the lookup table for the RGB level window.
void PrepareDifference(LocalStorage *localStorage)
void PrepareWipe(mitk::DataNode *datanode, LocalStorage *localStorage, const Point2D &currentIndex2D)
static Pointer New()
vtkScalarsToColors * GetLookupTable()
Get the lookup table for the RGB level window.
unsigned long GetCurrentWorldGeometry2DUpdateTime()
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:52
static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=NULL, bool overwrite=false)
Set the default properties for general image rendering.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
MAPRegistrationWrapper Wrapper class to allow the handling of MatchPoint registration objects as mitk...
const char *const nodeProp_RegEvalCurrentPosition
LocalStorage * GetLocalStorage(mitk::BaseRenderer *renderer)
Get the LocalStorage corresponding to the current renderer.
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
virtual unsigned long GetMTime() const override
Get the timestamp of the last change of the contents of this node or the referenced BaseData...
virtual const mitk::DataNode * GetMovingNode()
mitk::ExtractSliceFilter::Pointer m_Reslicer
The actual reslicer (one per renderer)
const PlaneGeometry * GetCurrentWorldGeometry2D()
virtual mitk::Image * GetTargetImage()
vtkSmartPointer< vtkPolyDataMapper > m_Mapper
Mapper of a 2D render window.
The LevelWindow class Class to store level/window values.
Internal class holding the mapper, actor, etc. for each of the 3 2D render windows.
static Pointer New()
void AddProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer=nullptr, bool overwrite=false)
Add the property (instance of BaseProperty) if it does not exist (or always ifoverwrite istrue) with ...
#define MITK_WARN
Definition: mitkLogMacros.h:23
The LookupTableProperty class Property to associate mitk::LookupTable to an mitk::DataNode.
const mitk::Image * GetMovingImage(void)
Get the moving image to map.
const mitk::Image * GetTargetImage(void)
Get the target image to map.
virtual void Update(mitk::BaseRenderer *renderer)
Checks whether this mapper needs to update itself and generate data.
static Pointer New()
const char *const nodeProp_RegEvalBlendFactor
itk::TimeStamp m_LastUpdateTime
Timestamp of last update of stored data.
RegEvaluationObject Class that containes all data to realize an evaluation of registrations via image...
vtkSmartPointer< vtkActor > m_Actor
Actor of a 2D render window.
const mitk::DataNode * GetTargetNode(void)
bool PropertyIsOutdated(const mitk::DataNode *regNode, const std::string &propName, const itk::TimeStamp &reference)
Image class for storing images.
Definition: mitkImage.h:76
void SetMaxOpacity(double maxOpacity)
Get/Set the upper window opacity for the alpha level window.
const char *const nodeProp_RegEvalWipeStyle
vtkSmartPointer< vtkTexture > m_Texture
The texture which is used to render the current slice.
vtkSmartPointer< vtkImageExtractComponents > m_TargetExtractFilter
void ApplyLevelWindow(mitk::BaseRenderer *renderer, const mitk::DataNode *dataNode, vtkMitkLevelWindowFilter *levelFilter)
ApplyLevelWindow Apply the level window for the given renderer.
Applies the grayvalue or color/opacity level window to scalar or RGB(A) images.
bool GetPropertyValue(const char *propertyKey, T &value, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for GenericProperty properties (T being the type of the second parameter...
Definition: mitkDataNode.h:275
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
Describes the geometry of a data object consisting of slices.
vtkSmartPointer< vtkLookupTable > m_ColorLookupTable
The lookuptables for colors and level window.
static Pointer New()
void PrepareContour(mitk::DataNode *datanode, LocalStorage *localStorage)
bool IsRotated() const
Returns true if an image is rotated, i.e. its geometry's transformation matrix has nonzero elements b...
Definition: mitkImage.cpp:1366
bool HasReferenceGeometry() const
static Pointer New()
void ApplyOpacity(mitk::BaseRenderer *renderer)
Set the opacity of the actor.
const mitk::DataNode * GetMovingNode(void)
void TransformActor(mitk::BaseRenderer *renderer)
Transforms the actor to the actual position in 3D.
~LocalStorage()
Default deconstructor of the local storage.
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer map(const InputImageType *input, const RegistrationType *registration, bool throwOnOutOfInputAreaError=false, const double &paddingValue=0, const ResultImageGeometryType *resultGeometry=NULL, bool throwOnMappingError=true, const double &errorValue=0, mitk::ImageMappingInterpolator::Type interpolatorType=mitk::ImageMappingInterpolator::Linear)
bool GetLevelWindow(mitk::LevelWindow &levelWindow, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="levelwindow") const
Convenience access method for level-window properties (instances of LevelWindowProperty) ...
const char *const nodeProp_RegEvalStyle
Describes a two-dimensional, rectangular plane.
void SetProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer=nullptr)
Set the property (instance of BaseProperty) with key propertyKey in the PropertyList of the renderer ...
const char *const nodeProp_RegEvalTargetContour
vtkSmartPointer< vtkPropAssembly > m_Actors
ScalarType GetUpperWindowBound() const
virtual void UpdateOutputInformation() override
static Pointer New()
vtkRenderer * GetVtkRenderer() const
void PrepareCheckerBoard(mitk::DataNode *datanode, LocalStorage *localStorage)
const mitk::MAPRegistrationWrapper * GetRegistration(void)
Get the target image to map.
vtkSmartPointer< vtkPolyData > m_EmptyPolyData
Empty vtkPolyData that is set when rendering geometry does not intersect the image geometry...
virtual bool IsValidTimeStep(TimeStepType timeStep) const =0
Test for the given time step if a geometry is availible.
LocalStorage()
Default constructor of the local storage.
void SetMinOpacity(double minOpacity)
Get/Set the lower window opacity for the alpha level window.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.