Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkImageVtkMapper2D.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 <mitkPixelType.h>
24 #include <mitkPlaneGeometry.h>
25 #include <mitkProperties.h>
26 #include <mitkPropertyNameHelper.h>
29 
30 //#include <mitkTransferFunction.h>
32 #include "mitkPlaneClipping.h"
34 
35 // MITK Rendering
36 #include "mitkImageVtkMapper2D.h"
40 
41 // VTK
42 #include <vtkCamera.h>
43 #include <vtkCellArray.h>
44 #include <vtkColorTransferFunction.h>
45 #include <vtkGeneralTransform.h>
46 #include <vtkImageChangeInformation.h>
47 #include <vtkImageData.h>
48 #include <vtkImageExtractComponents.h>
49 #include <vtkImageReslice.h>
50 #include <vtkLookupTable.h>
51 #include <vtkMatrix4x4.h>
52 #include <vtkPlaneSource.h>
53 #include <vtkPoints.h>
54 #include <vtkPolyDataMapper.h>
55 #include <vtkProperty.h>
56 #include <vtkTransform.h>
57 
58 // ITK
59 #include <itkRGBAPixel.h>
61 
63 {
64 }
65 
67 {
68  // The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) is listening to this event,
69  // in order to delete the images from the 3D RW.
70  this->InvokeEvent(itk::DeleteEvent());
71 }
72 
73 // set the two points defining the textured plane according to the dimension and spacing
74 void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6])
75 {
76  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
77 
78  float depth = this->CalculateLayerDepth(renderer);
79  // Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct
80  // plane size in crosshair rotation and swivel mode.
81  localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth);
82  // These two points define the axes of the plane in combination with the origin.
83  // Point 1 is the x-axis and point 2 the y-axis.
84  // Each plane is transformed according to the view (axial, coronal and saggital) afterwards.
85  localStorage->m_Plane->SetPoint1(planeBounds[1], planeBounds[2], depth); // P1: (xMax, yMin, depth)
86  localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); // P2: (xMin, yMax, depth)
87 }
88 
90 {
91  // get the clipping range to check how deep into z direction we can render images
92  double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1];
93 
94  // Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined
95  float depth = -maxRange * 0.01; // divide by 100
96  int layer = 0;
97  GetDataNode()->GetIntProperty("layer", layer, renderer);
98  // add the layer property for each image to render images with a higher layer on top of the others
99  depth += layer * 10; //*10: keep some room for each image (e.g. for QBalls in between)
100  if (depth > 0.0f)
101  {
102  depth = 0.0f;
103  MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead.";
104  }
105  return depth;
106 }
107 
109 {
110  return static_cast<const mitk::Image *>(GetDataNode()->GetData());
111 }
112 
114 {
115  // return the actor corresponding to the renderer
116  return m_LSH.GetLocalStorage(renderer)->m_Actors;
117 }
118 
120 {
121  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
122 
123  SetVtkMapperImmediateModeRendering(localStorage->m_Mapper);
124 
125  mitk::Image *image = const_cast<mitk::Image *>(this->GetInput());
126  mitk::DataNode *datanode = this->GetDataNode();
127  if (nullptr == image || !image->IsInitialized())
128  {
129  return;
130  }
131 
132  // check if there is a valid worldGeometry
133  const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
134  if (nullptr == worldGeometry || !worldGeometry->IsValid() || !worldGeometry->HasReferenceGeometry())
135  {
136  return;
137  }
138 
139  image->Update();
140 
141  // early out if there is no intersection of the current rendering geometry
142  // and the geometry of the image that is to be rendered.
143  if (!RenderingGeometryIntersectsImage(worldGeometry, image->GetSlicedGeometry()))
144  {
145  // set image to NULL, to clear the texture in 3D, because
146  // the latest image is used there if the plane is out of the geometry
147  // see bug-13275
148  localStorage->m_ReslicedImage = NULL;
149  localStorage->m_Mapper->SetInputData(localStorage->m_EmptyPolyData);
150  return;
151  }
152 
153  // set main input for ExtractSliceFilter
154  localStorage->m_Reslicer->SetInput(image);
155  localStorage->m_Reslicer->SetWorldGeometry(worldGeometry);
156  localStorage->m_Reslicer->SetTimeStep(this->GetTimestep());
157 
158  // set the transformation of the image to adapt reslice axis
159  localStorage->m_Reslicer->SetResliceTransformByGeometry(
160  image->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep()));
161 
162  // is the geometry of the slice based on the input image or the worldgeometry?
163  bool inPlaneResampleExtentByGeometry = false;
164  datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer);
165  localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry);
166 
167  // Initialize the interpolation mode for resampling; switch to nearest
168  // neighbor if the input image is too small.
169  if ((image->GetDimension() >= 3) && (image->GetDimension(2) > 1))
170  {
171  VtkResliceInterpolationProperty *resliceInterpolationProperty;
172  datanode->GetProperty(resliceInterpolationProperty, "reslice interpolation", renderer);
173 
174  int interpolationMode = VTK_RESLICE_NEAREST;
175  if (resliceInterpolationProperty != NULL)
176  {
177  interpolationMode = resliceInterpolationProperty->GetInterpolation();
178  }
179 
180  switch (interpolationMode)
181  {
182  case VTK_RESLICE_NEAREST:
183  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
184  break;
185  case VTK_RESLICE_LINEAR:
186  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR);
187  break;
188  case VTK_RESLICE_CUBIC:
189  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC);
190  break;
191  }
192  }
193  else
194  {
195  localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
196  }
197 
198  // set the vtk output property to true, makes sure that no unneeded mitk image convertion
199  // is done.
200  localStorage->m_Reslicer->SetVtkOutputRequest(true);
201 
202  // Thickslicing
203  int thickSlicesMode = 0;
204  int thickSlicesNum = 1;
205  // Thick slices parameters
206  if (image->GetPixelType().GetNumberOfComponents() == 1) // for now only single component are allowed
207  {
208  DataNode *dn = renderer->GetCurrentWorldPlaneGeometryNode();
209  if (dn)
210  {
211  ResliceMethodProperty *resliceMethodEnumProperty = 0;
212 
213  if (dn->GetProperty(resliceMethodEnumProperty, "reslice.thickslices", renderer) && resliceMethodEnumProperty)
214  thickSlicesMode = resliceMethodEnumProperty->GetValueAsId();
215 
216  IntProperty *intProperty = 0;
217  if (dn->GetProperty(intProperty, "reslice.thickslices.num", renderer) && intProperty)
218  {
219  thickSlicesNum = intProperty->GetValue();
220  if (thickSlicesNum < 1)
221  thickSlicesNum = 1;
222  }
223  }
224  else
225  {
226  MITK_WARN << "no associated widget plane data tree node found";
227  }
228  }
229 
230  const PlaneGeometry *planeGeometry = dynamic_cast<const PlaneGeometry *>(worldGeometry);
231 
232  if (thickSlicesMode > 0)
233  {
234  double dataZSpacing = 1.0;
235 
236  Vector3D normInIndex, normal;
237 
238  const mitk::AbstractTransformGeometry *abstractGeometry =
239  dynamic_cast<const AbstractTransformGeometry *>(worldGeometry);
240  if (abstractGeometry != NULL)
241  normal = abstractGeometry->GetPlane()->GetNormal();
242  else
243  {
244  if (planeGeometry != NULL)
245  {
246  normal = planeGeometry->GetNormal();
247  }
248  else
249  return; // no fitting geometry set
250  }
251  normal.Normalize();
252 
253  image->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep())->WorldToIndex(normal, normInIndex);
254 
255  dataZSpacing = 1.0 / normInIndex.GetNorm();
256 
257  localStorage->m_Reslicer->SetOutputDimensionality(3);
258  localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing);
259  localStorage->m_Reslicer->SetOutputExtentZDirection(-thickSlicesNum, 0 + thickSlicesNum);
260 
261  // Do the reslicing. Modified() is called to make sure that the reslicer is
262  // executed even though the input geometry information did not change; this
263  // is necessary when the input /em data, but not the /em geometry changes.
264  localStorage->m_TSFilter->SetThickSliceMode(thickSlicesMode - 1);
265  localStorage->m_TSFilter->SetInputData(localStorage->m_Reslicer->GetVtkOutput());
266 
267  // vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually
268  localStorage->m_Reslicer->Modified();
269  localStorage->m_Reslicer->Update();
270 
271  localStorage->m_TSFilter->Modified();
272  localStorage->m_TSFilter->Update();
273  localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput();
274  }
275  else
276  {
277  // this is needed when thick mode was enable bevore. These variable have to be reset to default values
278  localStorage->m_Reslicer->SetOutputDimensionality(2);
279  localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0);
280  localStorage->m_Reslicer->SetOutputExtentZDirection(0, 0);
281 
282  localStorage->m_Reslicer->Modified();
283  // start the pipeline with updating the largest possible, needed if the geometry of the input has changed
284  localStorage->m_Reslicer->UpdateLargestPossibleRegion();
285  localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput();
286  }
287 
288  // Bounds information for reslicing (only reuqired if reference geometry
289  // is present)
290  // this used for generating a vtkPLaneSource with the right size
291  double sliceBounds[6];
292  for (auto &sliceBound : sliceBounds)
293  {
294  sliceBound = 0.0;
295  }
296  localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds);
297 
298  // get the spacing of the slice
299  localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing();
300 
301  // calculate minimum bounding rect of IMAGE in texture
302  {
303  double textureClippingBounds[6];
304  for (auto &textureClippingBound : textureClippingBounds)
305  {
306  textureClippingBound = 0.0;
307  }
308  // Calculate the actual bounds of the transformed plane clipped by the
309  // dataset bounding box; this is required for drawing the texture at the
310  // correct position during 3D mapping.
311  mitk::PlaneClipping::CalculateClippedPlaneBounds(image->GetGeometry(), planeGeometry, textureClippingBounds);
312 
313  textureClippingBounds[0] = static_cast<int>(textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5);
314  textureClippingBounds[1] = static_cast<int>(textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5);
315  textureClippingBounds[2] = static_cast<int>(textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5);
316  textureClippingBounds[3] = static_cast<int>(textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5);
317 
318  // clipping bounds for cutting the image
319  localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds);
320  }
321 
322  // get the number of scalar components to distinguish between different image types
323  int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents();
324  // get the binary property
325  bool binary = false;
326  bool binaryOutline = false;
327  datanode->GetBoolProperty("binary", binary, renderer);
328  if (binary) // binary image
329  {
330  datanode->GetBoolProperty("outline binary", binaryOutline, renderer);
331  if (binaryOutline) // contour rendering
332  {
333  // get pixel type of vtk image
334  itk::ImageIOBase::IOComponentType componentType = static_cast<itk::ImageIOBase::IOComponentType>(image->GetPixelType().GetComponentType());
335  switch (componentType)
336  {
337  case itk::ImageIOBase::UCHAR:
338  // generate contours/outlines
339  localStorage->m_OutlinePolyData = CreateOutlinePolyData<unsigned char>(renderer);
340  break;
341  case itk::ImageIOBase::USHORT:
342  // generate contours/outlines
343  localStorage->m_OutlinePolyData = CreateOutlinePolyData<unsigned short>(renderer);
344  break;
345  default:
346  binaryOutline = false;
347  this->ApplyLookuptable(renderer);
348  MITK_WARN << "Type of all binary images should be unsigned char or unsigned short. Outline does not work on other pixel types!";
349  }
350  if (binaryOutline) // binary outline is still true --> add outline
351  {
352  float binaryOutlineWidth = 1.0;
353  if (datanode->GetFloatProperty("outline width", binaryOutlineWidth, renderer))
354  {
355  if (localStorage->m_Actors->GetNumberOfPaths() > 1)
356  {
357  float binaryOutlineShadowWidth = 1.5;
358  datanode->GetFloatProperty("outline shadow width", binaryOutlineShadowWidth, renderer);
359 
360  dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0))
361  ->GetProperty()
362  ->SetLineWidth(binaryOutlineWidth * binaryOutlineShadowWidth);
363  }
364  localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth);
365  }
366  }
367  }
368  else // standard binary image
369  {
370  if (numberOfComponents != 1)
371  {
372  MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!";
373  }
374  }
375  }
376 
377  this->ApplyOpacity(renderer);
378  this->ApplyRenderingMode(renderer);
379 
380  // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
381  localStorage->m_Texture->MapColorScalarsThroughLookupTableOff();
382 
383  int displayedComponent = 0;
384 
385  if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1)
386  {
387  localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent);
388  localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage);
389 
390  localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0));
391  }
392  else
393  {
394  // connect the input with the levelwindow filter
395  localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage);
396  }
397 
398  // check for texture interpolation property
399  bool textureInterpolation = false;
400  GetDataNode()->GetBoolProperty("texture interpolation", textureInterpolation, renderer);
401 
402  // set the interpolation modus according to the property
403  localStorage->m_Texture->SetInterpolate(textureInterpolation);
404 
405  // connect the texture with the output of the levelwindow filter
406  localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort());
407 
408  this->TransformActor(renderer);
409 
410  vtkActor *contourShadowActor = dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0));
411 
412  if (binary && binaryOutline) // connect the mapper with the polyData which contains the lines
413  {
414  // We need the contour for the binary outline property as actor
415  localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData);
416  localStorage->m_Actor->SetTexture(nullptr); // no texture for contours
417 
418  bool binaryOutlineShadow = false;
419  datanode->GetBoolProperty("outline binary shadow", binaryOutlineShadow, renderer);
420  if (binaryOutlineShadow)
421  {
422  contourShadowActor->SetVisibility(true);
423  }
424  else
425  {
426  contourShadowActor->SetVisibility(false);
427  }
428  }
429  else
430  { // Connect the mapper with the input texture. This is the standard case.
431  // setup the textured plane
432  this->GeneratePlane(renderer, sliceBounds);
433  // set the plane as input for the mapper
434  localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort());
435  // set the texture for the actor
436 
437  localStorage->m_Actor->SetTexture(localStorage->m_Texture);
438  contourShadowActor->SetVisibility(false);
439  }
440 
441  // We have been modified => save this for next Update()
442  localStorage->m_LastUpdateTime.Modified();
443 }
444 
446 {
447  LocalStorage *localStorage = this->GetLocalStorage(renderer);
448 
449  LevelWindow levelWindow;
450  this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelwindow");
451  localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange(levelWindow.GetLowerWindowBound(),
452  levelWindow.GetUpperWindowBound());
453 
454  mitk::LevelWindow opacLevelWindow;
455  if (this->GetDataNode()->GetLevelWindow(opacLevelWindow, renderer, "opaclevelwindow"))
456  {
457  // pass the opaque level window to the filter
458  localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound());
459  localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound());
460  }
461  else
462  {
463  // no opaque level window
464  localStorage->m_LevelWindowFilter->SetMinOpacity(0.0);
465  localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0);
466  }
467 }
468 
470 {
471  LocalStorage *localStorage = this->GetLocalStorage(renderer);
472 
473  float rgb[3] = {1.0f, 1.0f, 1.0f};
474 
475  // check for color prop and use it for rendering if it exists
476  // binary image hovering & binary image selection
477  bool hover = false;
478  bool selected = false;
479  bool binary = false;
480  GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer);
481  GetDataNode()->GetBoolProperty("selected", selected, renderer);
482  GetDataNode()->GetBoolProperty("binary", binary, renderer);
483  if (binary && hover && !selected)
484  {
485  mitk::ColorProperty::Pointer colorprop =
486  dynamic_cast<mitk::ColorProperty *>(GetDataNode()->GetProperty("binaryimage.hoveringcolor", renderer));
487  if (colorprop.IsNotNull())
488  {
489  memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float));
490  }
491  else
492  {
493  GetDataNode()->GetColor(rgb, renderer, "color");
494  }
495  }
496  if (binary && selected)
497  {
498  mitk::ColorProperty::Pointer colorprop =
499  dynamic_cast<mitk::ColorProperty *>(GetDataNode()->GetProperty("binaryimage.selectedcolor", renderer));
500  if (colorprop.IsNotNull())
501  {
502  memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float));
503  }
504  else
505  {
506  GetDataNode()->GetColor(rgb, renderer, "color");
507  }
508  }
509  if (!binary || (!hover && !selected))
510  {
511  GetDataNode()->GetColor(rgb, renderer, "color");
512  }
513 
514  double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; // conversion to double for VTK
515  dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv);
516  localStorage->m_Actor->GetProperty()->SetColor(rgbConv);
517 
518  if (localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1)
519  {
520  float rgb[3] = {1.0f, 1.0f, 1.0f};
521  mitk::ColorProperty::Pointer colorprop =
522  dynamic_cast<mitk::ColorProperty *>(GetDataNode()->GetProperty("outline binary shadow color", renderer));
523  if (colorprop.IsNotNull())
524  {
525  memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float));
526  }
527  double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; // conversion to double for VTK
528  dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv);
529  }
530 }
531 
533 {
534  LocalStorage *localStorage = this->GetLocalStorage(renderer);
535  float opacity = 1.0f;
536  // check for opacity prop and use it for rendering if it exists
537  GetDataNode()->GetOpacity(opacity, renderer, "opacity");
538  // set the opacity according to the properties
539  localStorage->m_Actor->GetProperty()->SetOpacity(opacity);
540  if (localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1)
541  {
542  dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0))
543  ->GetProperty()
544  ->SetOpacity(opacity);
545  }
546 }
547 
549 {
550  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
551 
552  bool binary = false;
553  this->GetDataNode()->GetBoolProperty("binary", binary, renderer);
554  if (binary) // is it a binary image?
555  {
556  // for binary images, we always use our default LuT and map every value to (0,1)
557  // the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window.
558  localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable);
559  }
560  else
561  {
562  // all other image types can make use of the rendering mode
565  dynamic_cast<mitk::RenderingModeProperty *>(this->GetDataNode()->GetProperty("Image Rendering.Mode", renderer));
566  if (mode.IsNotNull())
567  {
568  renderingMode = mode->GetRenderingMode();
569  }
570  switch (renderingMode)
571  {
573  MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color";
574  this->ApplyLookuptable(renderer);
575  this->ApplyLevelWindow(renderer);
576  break;
578  MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color";
579  this->ApplyColorTransferFunction(renderer);
580  this->ApplyLevelWindow(renderer);
581  break;
583  MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color";
584  this->ApplyLookuptable(renderer);
585  break;
587  MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color";
588  this->ApplyColorTransferFunction(renderer);
589  break;
590  default:
591  MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead.";
592  this->ApplyLookuptable(renderer);
593  this->ApplyLevelWindow(renderer);
594  break;
595  }
596  }
597  // we apply color for all images (including binaries).
598  this->ApplyColor(renderer);
599 }
600 
602 {
603  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
604  vtkLookupTable *usedLookupTable = localStorage->m_ColorLookupTable;
605 
606  // If lookup table or transferfunction use is requested...
607  mitk::LookupTableProperty::Pointer lookupTableProp =
608  dynamic_cast<mitk::LookupTableProperty *>(this->GetDataNode()->GetProperty("LookupTable"));
609 
610  if (lookupTableProp.IsNotNull()) // is a lookuptable set?
611  {
612  usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable();
613  }
614  else
615  {
616  //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'.
617  // A default (rainbow) lookup table will be used.
618  // Here have to do nothing. Warning for the user has been removed, due to unwanted console output
619  // in every interation of the rendering.
620  }
621  localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable);
622 }
623 
625 {
626  mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast<mitk::TransferFunctionProperty *>(
627  this->GetDataNode()->GetProperty("Image Rendering.Transfer Function", renderer));
628 
629  if (transferFunctionProp.IsNull())
630  {
631  MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image "
632  "Rendering.Transfer Function'. Nothing will be done.";
633  return;
634  }
635  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
636  // pass the transfer function to our level window filter
637  localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction());
638  localStorage->m_LevelWindowFilter->SetOpacityPiecewiseFunction(
639  transferFunctionProp->GetValue()->GetScalarOpacityFunction());
640 }
641 
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->GetInput());
653  if (data == NULL)
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 == NULL) || (dataTimeGeometry->CountTimeSteps() == 0) ||
664  (!dataTimeGeometry->IsValidTimeStep(this->GetTimestep())))
665  {
666  return;
667  }
668 
669  const DataNode *node = this->GetDataNode();
670  data->UpdateOutputInformation();
671  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
672 
673  // check if something important has changed and we need to rerender
674  if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified?
675  ||
676  (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified?
677  ||
678  (localStorage->m_LastUpdateTime <
679  renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified?
680  ||
681  (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) ||
682  (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified?
683  ||
684  (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()))
685  {
686  this->GenerateDataForRenderer(renderer);
687  }
688 
689  // since we have checked that nothing important has changed, we can set
690  // m_LastUpdateTime to the current time
691  localStorage->m_LastUpdateTime.Modified();
692 }
693 
695 {
696  mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(node->GetData());
697 
698  // Properties common for both images and segmentations
699  node->AddProperty("depthOffset", mitk::FloatProperty::New(0.0), renderer, overwrite);
700  node->AddProperty("outline binary", mitk::BoolProperty::New(false), renderer, overwrite);
701  node->AddProperty("outline width", mitk::FloatProperty::New(1.0), renderer, overwrite);
702  node->AddProperty("outline binary shadow", mitk::BoolProperty::New(false), renderer, overwrite);
703  node->AddProperty("outline binary shadow color", ColorProperty::New(0.0, 0.0, 0.0), renderer, overwrite);
704  node->AddProperty("outline shadow width", mitk::FloatProperty::New(1.5), renderer, overwrite);
705  if (image->IsRotated())
706  node->AddProperty("reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC));
707  else
708  node->AddProperty("reslice interpolation", mitk::VtkResliceInterpolationProperty::New());
709  node->AddProperty("texture interpolation", mitk::BoolProperty::New(false));
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
718  mitkLut->SetType(mitk::LookupTable::GRAYSCALE);
720  mitkLutProp->SetLookupTable(mitkLut);
721  node->SetProperty("LookupTable", mitkLutProp);
722 
723  std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed
724  if (node->GetStringProperty("dicom.pixel.PhotometricInterpretation", photometricInterpretation))
725  {
726  // modality provided by DICOM or other reader
727  if (photometricInterpretation.find("MONOCHROME1") != std::string::npos) // meaning: display MINIMUM pixels as WHITE
728  {
729  // Set inverse grayscale look-up table
730  mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE);
731  mitkLutProp->SetLookupTable(mitkLut);
732  node->SetProperty("LookupTable", mitkLutProp);
733  renderingModeProperty->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); // USE lookuptable
734  }
735  // Otherwise do nothing - the default grayscale look-up table has already been set
736  }
737 
738  bool isBinaryImage(false);
739  if (!node->GetBoolProperty("binary", isBinaryImage) && image->GetPixelType().GetNumberOfComponents() == 1)
740  {
741  // ok, property is not set, use heuristic to determine if this
742  // is a binary image
743  mitk::Image::Pointer centralSliceImage;
744  ScalarType minValue = 0.0;
745  ScalarType maxValue = 0.0;
746  ScalarType min2ndValue = 0.0;
747  ScalarType max2ndValue = 0.0;
749 
750  sliceSelector->SetInput(image);
751  sliceSelector->SetSliceNr(image->GetDimension(2) / 2);
752  sliceSelector->SetTimeNr(image->GetDimension(3) / 2);
753  sliceSelector->SetChannelNr(image->GetDimension(4) / 2);
754  sliceSelector->Update();
755  centralSliceImage = sliceSelector->GetOutput();
756  if (centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized())
757  {
758  minValue = centralSliceImage->GetStatistics()->GetScalarValueMin();
759  maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax();
760  min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin();
761  max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax();
762  }
763  if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue)
764  {
765  // centralSlice is strange, lets look at all data
766  minValue = image->GetStatistics()->GetScalarValueMin();
767  maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute();
768  min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute();
769  max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute();
770  }
771  isBinaryImage = (maxValue == min2ndValue && minValue == max2ndValue);
772  }
773 
774  std::string className = image->GetNameOfClass();
775  if (className != "TensorImage" && className != "QBallImage")
776  {
777  PixelType pixelType = image->GetPixelType();
778  size_t numComponents = pixelType.GetNumberOfComponents();
779 
780  if ((pixelType.GetPixelType() == itk::ImageIOBase::VECTOR && numComponents > 1) || numComponents == 2 ||
781  numComponents > 4)
782  {
783  node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite);
784  }
785  }
786 
787  // some more properties specific for a binary...
788  if (isBinaryImage)
789  {
790  node->AddProperty("opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite);
791  node->AddProperty("color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
792  node->AddProperty("binaryimage.selectedcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
793  node->AddProperty("binaryimage.selectedannotationcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
794  node->AddProperty("binaryimage.hoveringcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
795  node->AddProperty("binaryimage.hoveringannotationcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite);
796  node->AddProperty("binary", mitk::BoolProperty::New(true), renderer, overwrite);
797  node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite);
798  }
799  else //...or image type object
800  {
801  node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite);
802  node->AddProperty("color", ColorProperty::New(1.0, 1.0, 1.0), renderer, overwrite);
803  node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite);
804  node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite);
805  }
806 
807  if (image.IsNotNull() && image->IsInitialized())
808  {
809  if ((overwrite) || (node->GetProperty("levelwindow", renderer) == NULL))
810  {
811  /* initialize level/window from DICOM tags */
812  std::string sLevel = "";
813  std::string sWindow = "";
814 
816  0x0028, 0x1050, "dicom.voilut.WindowCenter", image->GetPropertyList(), sLevel) &&
818  0x0028, 0x1051, "dicom.voilut.WindowWidth", image->GetPropertyList(), sWindow))
819  {
820  float level = atof(sLevel.c_str());
821  float window = atof(sWindow.c_str());
822 
823  mitk::LevelWindow contrast;
824  std::string sSmallestPixelValueInSeries;
825  std::string sLargestPixelValueInSeries;
826 
828  0x0108,
829  "dicom.series.SmallestPixelValueInSeries",
830  image->GetPropertyList(),
831  sSmallestPixelValueInSeries) &&
833  0x0109,
834  "dicom.series.LargestPixelValueInSeries",
835  image->GetPropertyList(),
836  sLargestPixelValueInSeries))
837  {
838  float smallestPixelValueInSeries = atof(sSmallestPixelValueInSeries.c_str());
839  float largestPixelValueInSeries = atof(sLargestPixelValueInSeries.c_str());
840  contrast.SetRangeMinMax(smallestPixelValueInSeries - 1,
841  largestPixelValueInSeries + 1); // why not a little buffer?
842  // might remedy some l/w widget challenges
843  }
844  else
845  {
846  contrast.SetAuto(static_cast<mitk::Image *>(node->GetData()), false, true); // we need this as a fallback
847  }
848 
849  contrast.SetLevelWindow(level, window, true);
850  node->SetProperty("levelwindow", LevelWindowProperty::New(contrast), renderer);
851  }
852  }
853  if (((overwrite) || (node->GetProperty("opaclevelwindow", renderer) == NULL)) &&
854  (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) &&
855  (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR))
856  {
857  mitk::LevelWindow opaclevwin;
858  opaclevwin.SetRangeMinMax(0, 255);
859  opaclevwin.SetWindowBounds(0, 255);
861  node->SetProperty("opaclevelwindow", prop, renderer);
862  }
863  }
864  Superclass::SetDefaultProperties(node, renderer, overwrite);
865 }
866 
868 {
869  return m_LSH.GetLocalStorage(renderer);
870 }
871 
872 template <typename TPixel>
874 {
875  LocalStorage *localStorage = this->GetLocalStorage(renderer);
876 
877  // get the min and max index values of each direction
878  int *extent = localStorage->m_ReslicedImage->GetExtent();
879  int xMin = extent[0];
880  int xMax = extent[1];
881  int yMin = extent[2];
882  int yMax = extent[3];
883 
884  int *dims = localStorage->m_ReslicedImage->GetDimensions(); // dimensions of the image
885  int line = dims[0]; // how many pixels per line?
886  int x = xMin; // pixel index x
887  int y = yMin; // pixel index y
888 
889  // get the depth for each contour
890  float depth = CalculateLayerDepth(renderer);
891 
892  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); // the points to draw
893  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); // the lines to connect the points
894 
895  // We take the pointer to the first pixel of the image
896  TPixel* currentPixel = static_cast<TPixel*>(localStorage->m_ReslicedImage->GetScalarPointer());
897 
898  while (y <= yMax)
899  {
900  // if the current pixel value is set to something
901  if ((currentPixel) && (*currentPixel != 0))
902  {
903  // check in which direction a line is necessary
904  // a line is added if the neighbor of the current pixel has the value 0
905  // and if the pixel is located at the edge of the image
906 
907  // if vvvvv not the first line vvvvv
908  if (y > yMin && *(currentPixel - line) == 0)
909  { // x direction - bottom edge of the pixel
910  // add the 2 points
911  vtkIdType p1 =
912  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
913  vtkIdType p2 =
914  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
915  // add the line between both points
916  lines->InsertNextCell(2);
917  lines->InsertCellPoint(p1);
918  lines->InsertCellPoint(p2);
919  }
920 
921  // if vvvvv not the last line vvvvv
922  if (y < yMax && *(currentPixel + line) == 0)
923  { // x direction - top edge of the pixel
924  vtkIdType p1 =
925  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
926  vtkIdType p2 = points->InsertNextPoint(
927  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
928  lines->InsertNextCell(2);
929  lines->InsertCellPoint(p1);
930  lines->InsertCellPoint(p2);
931  }
932 
933  // if vvvvv not the first pixel vvvvv
934  if ((x > xMin || y > yMin) && *(currentPixel - 1) == 0)
935  { // y direction - left edge of the pixel
936  vtkIdType p1 =
937  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
938  vtkIdType p2 =
939  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
940  lines->InsertNextCell(2);
941  lines->InsertCellPoint(p1);
942  lines->InsertCellPoint(p2);
943  }
944 
945  // if vvvvv not the last pixel vvvvv
946  if ((y < yMax || (x < xMax)) && *(currentPixel + 1) == 0)
947  { // y direction - right edge of the pixel
948  vtkIdType p1 =
949  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
950  vtkIdType p2 = points->InsertNextPoint(
951  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
952  lines->InsertNextCell(2);
953  lines->InsertCellPoint(p1);
954  lines->InsertCellPoint(p2);
955  }
956 
957  /* now consider pixels at the edge of the image */
958 
959  // if vvvvv left edge of image vvvvv
960  if (x == xMin)
961  { // draw left edge of the pixel
962  vtkIdType p1 =
963  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
964  vtkIdType p2 =
965  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
966  lines->InsertNextCell(2);
967  lines->InsertCellPoint(p1);
968  lines->InsertCellPoint(p2);
969  }
970 
971  // if vvvvv right edge of image vvvvv
972  if (x == xMax)
973  { // draw right edge of the pixel
974  vtkIdType p1 =
975  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
976  vtkIdType p2 = points->InsertNextPoint(
977  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
978  lines->InsertNextCell(2);
979  lines->InsertCellPoint(p1);
980  lines->InsertCellPoint(p2);
981  }
982 
983  // if vvvvv bottom edge of image vvvvv
984  if (y == yMin)
985  { // draw bottom edge of the pixel
986  vtkIdType p1 =
987  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
988  vtkIdType p2 =
989  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
990  lines->InsertNextCell(2);
991  lines->InsertCellPoint(p1);
992  lines->InsertCellPoint(p2);
993  }
994 
995  // if vvvvv top edge of image vvvvv
996  if (y == yMax)
997  { // draw top edge of the pixel
998  vtkIdType p1 =
999  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
1000  vtkIdType p2 = points->InsertNextPoint(
1001  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
1002  lines->InsertNextCell(2);
1003  lines->InsertCellPoint(p1);
1004  lines->InsertCellPoint(p2);
1005  }
1006  } // end if currentpixel is set
1007 
1008  x++;
1009 
1010  if (x > xMax)
1011  { // reached end of line
1012  x = xMin;
1013  y++;
1014  }
1015 
1016  // Increase the pointer-position to the next pixel.
1017  // This is safe, as the while-loop and the x-reset logic above makes
1018  // sure we do not exceed the bounds of the image
1019  currentPixel++;
1020  } // end of while
1021 
1022  // Create a polydata to store everything in
1023  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
1024  // Add the points to the dataset
1025  polyData->SetPoints(points);
1026  // Add the lines to the dataset
1027  polyData->SetLines(lines);
1028  return polyData;
1029 }
1030 
1032 {
1033  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
1034  // get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital
1035  vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
1036  vtkSmartPointer<vtkMatrix4x4> matrix = localStorage->m_Reslicer->GetResliceAxes();
1037  trans->SetMatrix(matrix);
1038  // transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital)
1039  localStorage->m_Actor->SetUserTransform(trans);
1040  // transform the origin to center based coordinates, because MITK is center based.
1041  localStorage->m_Actor->SetPosition(-0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0);
1042 
1043  if (localStorage->m_Actors->GetNumberOfPaths() > 1)
1044  {
1045  vtkActor *secondaryActor = dynamic_cast<vtkActor *>(localStorage->m_Actors->GetParts()->GetItemAsObject(0));
1046  secondaryActor->SetUserTransform(trans);
1047  secondaryActor->SetPosition(-0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0);
1048  }
1049 }
1050 
1052  SlicedGeometry3D *imageGeometry)
1053 {
1054  // if either one of the two geometries is NULL we return true
1055  // for safety reasons
1056  if (renderingGeometry == NULL || imageGeometry == NULL)
1057  return true;
1058 
1059  // get the distance for the first cornerpoint
1060  ScalarType initialDistance = renderingGeometry->SignedDistance(imageGeometry->GetCornerPoint(0));
1061  for (int i = 1; i < 8; i++)
1062  {
1063  mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint(i);
1064 
1065  // get the distance to the other cornerpoints
1066  ScalarType distance = renderingGeometry->SignedDistance(cornerPoint);
1067 
1068  // if it has not the same signing as the distance of the first point
1069  if (initialDistance * distance < 0)
1070  {
1071  // we have an intersection and return true
1072  return true;
1073  }
1074  }
1075 
1076  // all distances have the same sign, no intersection and we return false
1077  return false;
1078 }
1079 
1081 {
1082 }
1083 
1085  : m_VectorComponentExtractor(vtkSmartPointer<vtkImageExtractComponents>::New())
1086 {
1088 
1089  // Do as much actions as possible in here to avoid double executions.
1103 
1104  // the following actions are always the same and thus can be performed
1105  // in the constructor for each image (i.e. the image-corresponding local storage)
1106  m_TSFilter->ReleaseDataFlagOn();
1107 
1109  // built a default lookuptable
1110  mitkLUT->SetType(mitk::LookupTable::GRAYSCALE);
1111  m_DefaultLookupTable = mitkLUT->GetVtkLookupTable();
1112 
1113  mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY);
1114  m_BinaryLookupTable = mitkLUT->GetVtkLookupTable();
1115 
1116  mitkLUT->SetType(mitk::LookupTable::LEGACY_RAINBOW_COLOR);
1117  m_ColorLookupTable = mitkLUT->GetVtkLookupTable();
1118 
1119  // do not repeat the texture (the image)
1120  m_Texture->RepeatOff();
1121 
1122  // set the mapper for the actor
1123  m_Actor->SetMapper(m_Mapper);
1124 
1125  vtkSmartPointer<vtkActor> outlineShadowActor = vtkSmartPointer<vtkActor>::New();
1126  outlineShadowActor->SetMapper(m_Mapper);
1127 
1128  m_Actors->AddPart(outlineShadowActor);
1129  m_Actors->AddPart(m_Actor);
1130 }
void SetWindowBounds(ScalarType lowerBound, ScalarType upperBound, bool expandRangesIfNecessary=true)
float CalculateLayerDepth(mitk::BaseRenderer *renderer)
This method uses the vtkCamera clipping range and the layer property to calcualte the depth of the ob...
itk::TimeStamp m_LastUpdateTime
Timestamp of last update of stored data.
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is NULL, the BaseRenderer-independent PropertyList ...
static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=NULL, bool overwrite=false)
Set the default properties for general image rendering.
The TransferFunctionProperty class Property class for the mitk::TransferFunction. ...
virtual DataNode * GetCurrentWorldPlaneGeometryNode()
Get a DataNode pointing to a data object containing the current 2D-worldgeometry. ...
static char * line
Definition: svm.cpp:2884
ScalarType GetLowerWindowBound() const
void ApplyRenderingMode(mitk::BaseRenderer *renderer)
This method switches between different rendering modes (e.g. use a lookup table or a transfer functio...
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 ...
vtkSmartPointer< vtkActor > m_Actor
Actor of a 2D render window.
void ApplyLookuptable(mitk::BaseRenderer *renderer)
This method applies (or modifies) the lookuptable for all types of images.
~LocalStorage()
Default deconstructor of the local storage.
void ApplyOpacity(mitk::BaseRenderer *renderer)
Set the opacity of the actor.
static Pointer New()
virtual bool IsValid() const
Is this BaseGeometry in a state that is valid?
#define MITK_ERROR
Definition: mitkLogMacros.h:24
vtkSmartPointer< vtkImageExtractComponents > m_VectorComponentExtractor
double ScalarType
virtual void Update(mitk::BaseRenderer *renderer) override
Checks whether this mapper needs to update itself and generate data.
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
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...
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)
LocalStorage * GetLocalStorage(mitk::BaseRenderer *renderer)
Get the LocalStorage corresponding to the current renderer.
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
static Pointer New()
bool RenderingGeometryIntersectsImage(const PlaneGeometry *renderingGeometry, SlicedGeometry3D *imageGeometry)
Calculates whether the given rendering geometry intersects the given SlicedGeometry3D.
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:52
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
itk::ImageIOBase::IOPixelType GetPixelType() const
static Pointer New()
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 unsigned long GetMTime() const override
Get the timestamp of the last change of the contents of this node or the referenced BaseData...
void ApplyColorTransferFunction(mitk::BaseRenderer *renderer)
This method applies a color transfer function. Internally, a vtkColorTransferFunction is used...
vtkSmartPointer< vtkLookupTable > m_ColorLookupTable
Vector3D GetNormal() const
Normal of the plane.
vtkSmartPointer< vtkPropAssembly > m_Actors
bool GetStringProperty(const char *propertyKey, std::string &string, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for string properties (instances of StringProperty)
void SetRangeMinMax(ScalarType min, ScalarType max)
The LevelWindow class Class to store level/window values.
static Pointer New()
virtual vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
vtkSmartPointer< vtkLookupTable > m_DefaultLookupTable
The lookuptables for colors and level window.
virtual const PlaneGeometry * GetPlane()
Get the rectangular area that is used for transformation by m_VtkAbstractTransform and therewith defi...
vtkSmartPointer< vtkPolyData > m_OutlinePolyData
PolyData object containg all lines/points needed for outlining the contour. This container is used to...
The ColorProperty class RGB color property.
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.
vtkSmartPointer< vtkMitkLevelWindowFilter > m_LevelWindowFilter
This filter is used to apply the level window to Grayvalue and RBG(A) images.
virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
Does the actual resampling, without rendering the image yet. All the data is generated inside this me...
static Pointer New()
mitk::ScalarType * m_mmPerPixel
mmPerPixel relation between pixel and mm. (World spacing).
const mitk::Image * GetInput(void)
Get the Image to map.
bool GetFloatProperty(const char *propertyKey, float &floatValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for float properties (instances of FloatProperty)
vtkSmartPointer< vtkPolyDataMapper > m_Mapper
Mapper of a 2D render window.
Image class for storing images.
Definition: mitkImage.h:76
vtkSmartPointer< vtkPolyData > m_EmptyPolyData
Empty vtkPolyData that is set when rendering geometry does not intersect the image geometry...
void ApplyLevelWindow(mitk::BaseRenderer *renderer)
ApplyLevelWindow Apply the level window for the given renderer.
vtkSmartPointer< vtkTexture > m_Texture
The texture which is used to render the current slice.
Describes a geometry defined by an vtkAbstractTransform and a plane.
void ApplyColor(mitk::BaseRenderer *renderer)
Set the color of the image/polydata.
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
vtkSmartPointer< vtkMitkThickSlicesFilter > m_TSFilter
Filter for thick slices.
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.
void TransformActor(mitk::BaseRenderer *renderer)
Transforms the actor to the actual position in 3D.
static Pointer New()
vtkSmartPointer< vtkLookupTable > m_BinaryLookupTable
bool HasReferenceGeometry() const
static Pointer New()
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
Internal class holding the mapper, actor, etc. for each of the 3 2D render windows.
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
vtkSmartPointer< vtkPolyData > CreateOutlinePolyData(mitk::BaseRenderer *renderer)
Generates a vtkPolyData object containing the outline of a given binary slice.
unsigned long GetCurrentWorldPlaneGeometryUpdateTime()
Get timestamp of last call of SetCurrentWorldPlaneGeometry.
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
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 ...
ScalarType GetUpperWindowBound() const
void GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6])
Generates a plane according to the size of the resliced image in milimeters.
virtual void UpdateOutputInformation() override
vtkSmartPointer< vtkPlaneSource > m_Plane
Plane on which the slice is rendered as texture.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
static Pointer New()
vtkRenderer * GetVtkRenderer() const
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
bool MITKCORE_EXPORT GetBackwardsCompatibleDICOMProperty(unsigned int group, unsigned int element, std::string const &backwardsCompatiblePropertyName, PropertyList const *propertyList, std::string &propertyValue)
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.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
Class for defining the data type of pixels.
Definition: mitkPixelType.h:55
mitk::ExtractSliceFilter::Pointer m_Reslicer
The actual reslicer (one per renderer)
virtual IdType GetValueAsId() const
virtual T GetValue() const
vtkSmartPointer< vtkImageData > m_ReslicedImage
Current slice of a 2D render window.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.