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