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