Medical Imaging Interaction Toolkit  2018.4.99-c0f884b2
Medical Imaging Interaction Toolkit
mitkLabelSetImageVtkMapper2D.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 
14 
15 // MITK
17 #include <mitkDataNode.h>
18 #include <mitkImageSliceSelector.h>
22 #include <mitkPixelType.h>
23 #include <mitkPlaneClipping.h>
24 #include <mitkPlaneGeometry.h>
25 #include <mitkProperties.h>
27 #include <mitkTimeSlicedGeometry.h>
30 
31 // MITK Rendering
35 
36 // VTK
37 #include <vtkCamera.h>
38 #include <vtkCellArray.h>
39 #include <vtkImageData.h>
40 #include <vtkImageReslice.h>
41 #include <vtkLookupTable.h>
42 #include <vtkMatrix4x4.h>
43 #include <vtkPlaneSource.h>
44 #include <vtkPoints.h>
45 #include <vtkPolyData.h>
46 #include <vtkPolyDataMapper.h>
47 #include <vtkProperty.h>
48 #include <vtkTransform.h>
49 //#include <vtkOpenGLTexture.h>
50 
51 // ITK
52 #include <itkRGBAPixel.h>
54 
56 {
57 }
58 
60 {
61 }
62 
64 {
65  // return the actor corresponding to the renderer
66  return m_LSH.GetLocalStorage(renderer)->m_Actors;
67 }
68 
70  mitk::BaseRenderer *renderer)
71 {
72  return m_LSH.GetLocalStorage(renderer);
73 }
74 
76 {
77  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
78  mitk::DataNode *node = this->GetDataNode();
79  auto *image = dynamic_cast<mitk::LabelSetImage *>(node->GetData());
80  assert(image && image->IsInitialized());
81 
82  // check if there is a valid worldGeometry
83  const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
84  if ((worldGeometry == nullptr) || (!worldGeometry->IsValid()) || (!worldGeometry->HasReferenceGeometry()))
85  return;
86 
87  image->Update();
88 
89  int numberOfLayers = image->GetNumberOfLayers();
90  int activeLayer = image->GetActiveLayer();
91 
92  float opacity = 1.0f;
93  node->GetOpacity(opacity, renderer, "opacity");
94 
95  if (numberOfLayers != localStorage->m_NumberOfLayers)
96  {
97  localStorage->m_NumberOfLayers = numberOfLayers;
98  localStorage->m_ReslicedImageVector.clear();
99  localStorage->m_ReslicerVector.clear();
100  localStorage->m_LayerTextureVector.clear();
101  localStorage->m_LevelWindowFilterVector.clear();
102  localStorage->m_LayerMapperVector.clear();
103  localStorage->m_LayerActorVector.clear();
104 
105  localStorage->m_Actors = vtkSmartPointer<vtkPropAssembly>::New();
106 
107  for (int lidx = 0; lidx < numberOfLayers; ++lidx)
108  {
109  localStorage->m_ReslicedImageVector.push_back(vtkSmartPointer<vtkImageData>::New());
110  localStorage->m_ReslicerVector.push_back(mitk::ExtractSliceFilter::New());
111  localStorage->m_LayerTextureVector.push_back(vtkSmartPointer<vtkNeverTranslucentTexture>::New());
112  localStorage->m_LevelWindowFilterVector.push_back(vtkSmartPointer<vtkMitkLevelWindowFilter>::New());
113  localStorage->m_LayerMapperVector.push_back(vtkSmartPointer<vtkPolyDataMapper>::New());
114  localStorage->m_LayerActorVector.push_back(vtkSmartPointer<vtkActor>::New());
115 
116  // do not repeat the texture (the image)
117  localStorage->m_LayerTextureVector[lidx]->RepeatOff();
118 
119  // set corresponding mappers for the actors
120  localStorage->m_LayerActorVector[lidx]->SetMapper(localStorage->m_LayerMapperVector[lidx]);
121 
122  localStorage->m_Actors->AddPart(localStorage->m_LayerActorVector[lidx]);
123  }
124 
125  localStorage->m_Actors->AddPart(localStorage->m_OutlineShadowActor);
126  localStorage->m_Actors->AddPart(localStorage->m_OutlineActor);
127  }
128 
129  // early out if there is no intersection of the current rendering geometry
130  // and the geometry of the image that is to be rendered.
131  if (!RenderingGeometryIntersectsImage(worldGeometry, image->GetSlicedGeometry()))
132  {
133  // set image to nullptr, to clear the texture in 3D, because
134  // the latest image is used there if the plane is out of the geometry
135  // see bug-13275
136  for (int lidx = 0; lidx < numberOfLayers; ++lidx)
137  {
138  localStorage->m_ReslicedImageVector[lidx] = nullptr;
139  localStorage->m_LayerMapperVector[lidx]->SetInputData(localStorage->m_EmptyPolyData);
140  localStorage->m_OutlineActor->SetVisibility(false);
141  localStorage->m_OutlineShadowActor->SetVisibility(false);
142  }
143  return;
144  }
145 
146  for (int lidx = 0; lidx < numberOfLayers; ++lidx)
147  {
148  mitk::Image *layerImage = nullptr;
149 
150  // set main input for ExtractSliceFilter
151  if (lidx == activeLayer)
152  layerImage = image;
153  else
154  layerImage = image->GetLayerImage(lidx);
155 
156  localStorage->m_ReslicerVector[lidx]->SetInput(layerImage);
157  localStorage->m_ReslicerVector[lidx]->SetWorldGeometry(worldGeometry);
158  localStorage->m_ReslicerVector[lidx]->SetTimeStep(this->GetTimestep());
159 
160  // set the transformation of the image to adapt reslice axis
161  localStorage->m_ReslicerVector[lidx]->SetResliceTransformByGeometry(
162  layerImage->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep()));
163 
164  // is the geometry of the slice based on the image image or the worldgeometry?
165  bool inPlaneResampleExtentByGeometry = false;
166  node->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer);
167  localStorage->m_ReslicerVector[lidx]->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry);
168  localStorage->m_ReslicerVector[lidx]->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST);
169  localStorage->m_ReslicerVector[lidx]->SetVtkOutputRequest(true);
170 
171  // this is needed when thick mode was enabled before. These variables have to be reset to default values
172  localStorage->m_ReslicerVector[lidx]->SetOutputDimensionality(2);
173  localStorage->m_ReslicerVector[lidx]->SetOutputSpacingZDirection(1.0);
174  localStorage->m_ReslicerVector[lidx]->SetOutputExtentZDirection(0, 0);
175 
176  // Bounds information for reslicing (only required if reference geometry is present)
177  // this used for generating a vtkPLaneSource with the right size
178  double sliceBounds[6];
179  sliceBounds[0] = 0.0;
180  sliceBounds[1] = 0.0;
181  sliceBounds[2] = 0.0;
182  sliceBounds[3] = 0.0;
183  sliceBounds[4] = 0.0;
184  sliceBounds[5] = 0.0;
185 
186  localStorage->m_ReslicerVector[lidx]->GetClippedPlaneBounds(sliceBounds);
187 
188  // setup the textured plane
189  this->GeneratePlane(renderer, sliceBounds);
190 
191  // get the spacing of the slice
192  localStorage->m_mmPerPixel = localStorage->m_ReslicerVector[lidx]->GetOutputSpacing();
193  localStorage->m_ReslicerVector[lidx]->Modified();
194  // start the pipeline with updating the largest possible, needed if the geometry of the image has changed
195  localStorage->m_ReslicerVector[lidx]->UpdateLargestPossibleRegion();
196  localStorage->m_ReslicedImageVector[lidx] = localStorage->m_ReslicerVector[lidx]->GetVtkOutput();
197 
198  const auto *planeGeometry = dynamic_cast<const PlaneGeometry *>(worldGeometry);
199 
200  double textureClippingBounds[6];
201  for (auto &textureClippingBound : textureClippingBounds)
202  {
203  textureClippingBound = 0.0;
204  }
205 
206  // Calculate the actual bounds of the transformed plane clipped by the
207  // dataset bounding box; this is required for drawing the texture at the
208  // correct position during 3D mapping.
209  mitk::PlaneClipping::CalculateClippedPlaneBounds(layerImage->GetGeometry(), planeGeometry, textureClippingBounds);
210 
211  textureClippingBounds[0] = static_cast<int>(textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5);
212  textureClippingBounds[1] = static_cast<int>(textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5);
213  textureClippingBounds[2] = static_cast<int>(textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5);
214  textureClippingBounds[3] = static_cast<int>(textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5);
215 
216  // clipping bounds for cutting the imageLayer
217  localStorage->m_LevelWindowFilterVector[lidx]->SetClippingBounds(textureClippingBounds);
218 
219  localStorage->m_LevelWindowFilterVector[lidx]->SetLookupTable(
220  image->GetLabelSet(lidx)->GetLookupTable()->GetVtkLookupTable());
221 
222  // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
223  localStorage->m_LayerTextureVector[lidx]->SetColorModeToDirectScalars();
224 
225  // connect the imageLayer with the levelwindow filter
226  localStorage->m_LevelWindowFilterVector[lidx]->SetInputData(localStorage->m_ReslicedImageVector[lidx]);
227  // connect the texture with the output of the levelwindow filter
228 
229  // check for texture interpolation property
230  bool textureInterpolation = false;
231  node->GetBoolProperty("texture interpolation", textureInterpolation, renderer);
232 
233  // set the interpolation modus according to the property
234  localStorage->m_LayerTextureVector[lidx]->SetInterpolate(textureInterpolation);
235 
236  localStorage->m_LayerTextureVector[lidx]->SetInputConnection(
237  localStorage->m_LevelWindowFilterVector[lidx]->GetOutputPort());
238 
239  this->TransformActor(renderer);
240 
241  // set the plane as input for the mapper
242  localStorage->m_LayerMapperVector[lidx]->SetInputConnection(localStorage->m_Plane->GetOutputPort());
243 
244  // set the texture for the actor
245  localStorage->m_LayerActorVector[lidx]->SetTexture(localStorage->m_LayerTextureVector[lidx]);
246  localStorage->m_LayerActorVector[lidx]->GetProperty()->SetOpacity(opacity);
247  }
248 
249  mitk::Label* activeLabel = image->GetActiveLabel(activeLayer);
250  if (nullptr != activeLabel)
251  {
252  bool contourActive = false;
253  node->GetBoolProperty("labelset.contour.active", contourActive, renderer);
254  if (contourActive && activeLabel->GetVisible()) //contour rendering
255  {
256  //generate contours/outlines
257  localStorage->m_OutlinePolyData =
258  this->CreateOutlinePolyData(renderer, localStorage->m_ReslicedImageVector[activeLayer], activeLabel->GetValue());
259  localStorage->m_OutlineActor->SetVisibility(true);
260  localStorage->m_OutlineShadowActor->SetVisibility(true);
261  const mitk::Color& color = activeLabel->GetColor();
262  localStorage->m_OutlineActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue());
263  localStorage->m_OutlineShadowActor->GetProperty()->SetColor(0, 0, 0);
264 
265  float contourWidth(2.0);
266  node->GetFloatProperty("labelset.contour.width", contourWidth, renderer);
267  localStorage->m_OutlineActor->GetProperty()->SetLineWidth(contourWidth);
268  localStorage->m_OutlineShadowActor->GetProperty()->SetLineWidth(contourWidth * 1.5);
269 
270  localStorage->m_OutlineActor->GetProperty()->SetOpacity(opacity);
271  localStorage->m_OutlineShadowActor->GetProperty()->SetOpacity(opacity);
272 
273  localStorage->m_OutlineMapper->SetInputData(localStorage->m_OutlinePolyData);
274  return;
275  }
276  }
277  localStorage->m_OutlineActor->SetVisibility(false);
278  localStorage->m_OutlineShadowActor->SetVisibility(false);
279 }
280 
282  SlicedGeometry3D *imageGeometry)
283 {
284  // if either one of the two geometries is nullptr we return true
285  // for safety reasons
286  if (renderingGeometry == nullptr || imageGeometry == nullptr)
287  return true;
288 
289  // get the distance for the first cornerpoint
290  ScalarType initialDistance = renderingGeometry->SignedDistance(imageGeometry->GetCornerPoint(0));
291  for (int i = 1; i < 8; i++)
292  {
293  mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint(i);
294 
295  // get the distance to the other cornerpoints
296  ScalarType distance = renderingGeometry->SignedDistance(cornerPoint);
297 
298  // if it has not the same signing as the distance of the first point
299  if (initialDistance * distance < 0)
300  {
301  // we have an intersection and return true
302  return true;
303  }
304  }
305 
306  // all distances have the same sign, no intersection and we return false
307  return false;
308 }
309 
311  vtkImageData *image,
312  int pixelValue)
313 {
314  LocalStorage *localStorage = this->GetLocalStorage(renderer);
315 
316  // get the min and max index values of each direction
317  int *extent = image->GetExtent();
318  int xMin = extent[0];
319  int xMax = extent[1];
320  int yMin = extent[2];
321  int yMax = extent[3];
322 
323  int *dims = image->GetDimensions(); // dimensions of the image
324  int line = dims[0]; // how many pixels per line?
325  int x = xMin; // pixel index x
326  int y = yMin; // pixel index y
327 
328  // get the depth for each contour
329  float depth = this->CalculateLayerDepth(renderer);
330 
331  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); // the points to draw
332  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); // the lines to connect the points
333 
334  // We take the pointer to the first pixel of the image
335  auto *currentPixel = static_cast<mitk::Label::PixelType *>(image->GetScalarPointer());
336 
337  while (y <= yMax)
338  {
339  // if the current pixel value is set to something
340  if ((currentPixel) && (*currentPixel == pixelValue))
341  {
342  // check in which direction a line is necessary
343  // a line is added if the neighbor of the current pixel has the value 0
344  // and if the pixel is located at the edge of the image
345 
346  // if vvvvv not the first line vvvvv
347  if (y > yMin && *(currentPixel - line) != pixelValue)
348  { // x direction - bottom edge of the pixel
349  // add the 2 points
350  vtkIdType p1 =
351  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
352  vtkIdType p2 =
353  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
354  // add the line between both points
355  lines->InsertNextCell(2);
356  lines->InsertCellPoint(p1);
357  lines->InsertCellPoint(p2);
358  }
359 
360  // if vvvvv not the last line vvvvv
361  if (y < yMax && *(currentPixel + line) != pixelValue)
362  { // x direction - top edge of the pixel
363  vtkIdType p1 =
364  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
365  vtkIdType p2 = points->InsertNextPoint(
366  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
367  lines->InsertNextCell(2);
368  lines->InsertCellPoint(p1);
369  lines->InsertCellPoint(p2);
370  }
371 
372  // if vvvvv not the first pixel vvvvv
373  if ((x > xMin || y > yMin) && *(currentPixel - 1) != pixelValue)
374  { // y direction - left edge of the pixel
375  vtkIdType p1 =
376  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
377  vtkIdType p2 =
378  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
379  lines->InsertNextCell(2);
380  lines->InsertCellPoint(p1);
381  lines->InsertCellPoint(p2);
382  }
383 
384  // if vvvvv not the last pixel vvvvv
385  if ((y < yMax || (x < xMax)) && *(currentPixel + 1) != pixelValue)
386  { // y direction - right edge of the pixel
387  vtkIdType p1 =
388  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
389  vtkIdType p2 = points->InsertNextPoint(
390  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
391  lines->InsertNextCell(2);
392  lines->InsertCellPoint(p1);
393  lines->InsertCellPoint(p2);
394  }
395 
396  /* now consider pixels at the edge of the image */
397 
398  // if vvvvv left edge of image vvvvv
399  if (x == xMin)
400  { // draw left edge of the pixel
401  vtkIdType p1 =
402  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
403  vtkIdType p2 =
404  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
405  lines->InsertNextCell(2);
406  lines->InsertCellPoint(p1);
407  lines->InsertCellPoint(p2);
408  }
409 
410  // if vvvvv right edge of image vvvvv
411  if (x == xMax)
412  { // draw right edge of the pixel
413  vtkIdType p1 =
414  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
415  vtkIdType p2 = points->InsertNextPoint(
416  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
417  lines->InsertNextCell(2);
418  lines->InsertCellPoint(p1);
419  lines->InsertCellPoint(p2);
420  }
421 
422  // if vvvvv bottom edge of image vvvvv
423  if (y == yMin)
424  { // draw bottom edge of the pixel
425  vtkIdType p1 =
426  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
427  vtkIdType p2 =
428  points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth);
429  lines->InsertNextCell(2);
430  lines->InsertCellPoint(p1);
431  lines->InsertCellPoint(p2);
432  }
433 
434  // if vvvvv top edge of image vvvvv
435  if (y == yMax)
436  { // draw top edge of the pixel
437  vtkIdType p1 =
438  points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
439  vtkIdType p2 = points->InsertNextPoint(
440  (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth);
441  lines->InsertNextCell(2);
442  lines->InsertCellPoint(p1);
443  lines->InsertCellPoint(p2);
444  }
445  } // end if currentpixel is set
446 
447  x++;
448 
449  if (x > xMax)
450  { // reached end of line
451  x = xMin;
452  y++;
453  }
454 
455  // Increase the pointer-position to the next pixel.
456  // This is safe, as the while-loop and the x-reset logic above makes
457  // sure we do not exceed the bounds of the image
458  currentPixel++;
459  } // end of while
460 
461  // Create a polydata to store everything in
462  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
463  // Add the points to the dataset
464  polyData->SetPoints(points);
465  // Add the lines to the dataset
466  polyData->SetLines(lines);
467  return polyData;
468 }
469 
471 {
472  LocalStorage *localStorage = this->GetLocalStorage(renderer);
473  localStorage->m_OutlineActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue());
474  localStorage->m_OutlineShadowActor->GetProperty()->SetColor(0, 0, 0);
475 }
476 
478 {
479  LocalStorage *localStorage = this->GetLocalStorage(renderer);
480  float opacity = 1.0f;
481  this->GetDataNode()->GetOpacity(opacity, renderer, "opacity");
482  localStorage->m_LayerActorVector[layer]->GetProperty()->SetOpacity(opacity);
483  localStorage->m_OutlineActor->GetProperty()->SetOpacity(opacity);
484  localStorage->m_OutlineShadowActor->GetProperty()->SetOpacity(opacity);
485 }
486 
488 {
489  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
490  auto *input = dynamic_cast<mitk::LabelSetImage *>(this->GetDataNode()->GetData());
491  localStorage->m_LevelWindowFilterVector[layer]->SetLookupTable(
492  input->GetLabelSet(layer)->GetLookupTable()->GetVtkLookupTable());
493 }
494 
496 {
497  bool visible = true;
498  const DataNode *node = this->GetDataNode();
499  node->GetVisibility(visible, renderer, "visible");
500 
501  if (!visible)
502  return;
503 
504  auto *image = dynamic_cast<mitk::LabelSetImage *>(node->GetData());
505 
506  if (image == nullptr || image->IsInitialized() == false)
507  return;
508 
509  // Calculate time step of the image data for the specified renderer (integer value)
510  this->CalculateTimeStep(renderer);
511 
512  // Check if time step is valid
513  const TimeGeometry *dataTimeGeometry = image->GetTimeGeometry();
514  if ((dataTimeGeometry == nullptr) || (dataTimeGeometry->CountTimeSteps() == 0) ||
515  (!dataTimeGeometry->IsValidTimeStep(this->GetTimestep())))
516  {
517  return;
518  }
519 
520  image->UpdateOutputInformation();
521  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
522 
523  // check if something important has changed and we need to re-render
524 
525  if ((localStorage->m_LastDataUpdateTime < image->GetMTime()) ||
526  (localStorage->m_LastDataUpdateTime < image->GetPipelineMTime()) ||
527  (localStorage->m_LastDataUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) ||
528  (localStorage->m_LastDataUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()))
529  {
530  this->GenerateDataForRenderer(renderer);
531  localStorage->m_LastDataUpdateTime.Modified();
532  }
533  else if ((localStorage->m_LastPropertyUpdateTime < node->GetPropertyList()->GetMTime()) ||
534  (localStorage->m_LastPropertyUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ||
535  (localStorage->m_LastPropertyUpdateTime < image->GetPropertyList()->GetMTime()))
536  {
537  this->GenerateDataForRenderer(renderer);
538  localStorage->m_LastPropertyUpdateTime.Modified();
539  }
540 }
541 
542 // set the two points defining the textured plane according to the dimension and spacing
544 {
545  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
546 
547  float depth = this->CalculateLayerDepth(renderer);
548  // Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct
549  // plane size in crosshair rotation and swivel mode.
550  localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth);
551  // These two points define the axes of the plane in combination with the origin.
552  // Point 1 is the x-axis and point 2 the y-axis.
553  // Each plane is transformed according to the view (axial, coronal and saggital) afterwards.
554  localStorage->m_Plane->SetPoint1(planeBounds[1], planeBounds[2], depth); // P1: (xMax, yMin, depth)
555  localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); // P2: (xMin, yMax, depth)
556 }
557 
559 {
560  // get the clipping range to check how deep into z direction we can render images
561  double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1];
562 
563  // Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined
564  float depth = -maxRange * 0.01; // divide by 100
565  int layer = 0;
566  GetDataNode()->GetIntProperty("layer", layer, renderer);
567  // add the layer property for each image to render images with a higher layer on top of the others
568  depth += layer * 10; //*10: keep some room for each image (e.g. for ODFs in between)
569  if (depth > 0.0f)
570  {
571  depth = 0.0f;
572  MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead.";
573  }
574  return depth;
575 }
576 
578 {
579  LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
580  // get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital
581  vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
582  vtkSmartPointer<vtkMatrix4x4> matrix = localStorage->m_ReslicerVector[0]->GetResliceAxes(); // same for all layers
583  trans->SetMatrix(matrix);
584 
585  for (int lidx = 0; lidx < localStorage->m_NumberOfLayers; ++lidx)
586  {
587  // transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital)
588  localStorage->m_LayerActorVector[lidx]->SetUserTransform(trans);
589  // transform the origin to center based coordinates, because MITK is center based.
590  localStorage->m_LayerActorVector[lidx]->SetPosition(
591  -0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0);
592  }
593  // same for outline actor
594  localStorage->m_OutlineActor->SetUserTransform(trans);
595  localStorage->m_OutlineActor->SetPosition(
596  -0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0);
597  // same for outline shadow actor
598  localStorage->m_OutlineShadowActor->SetUserTransform(trans);
599  localStorage->m_OutlineShadowActor->SetPosition(
600  -0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0);
601 }
602 
604  mitk::BaseRenderer *renderer,
605  bool overwrite)
606 {
607  // add/replace the following properties
608  node->SetProperty("opacity", FloatProperty::New(1.0f), renderer);
609  node->SetProperty("binary", BoolProperty::New(false), renderer);
610 
611  mitk::RenderingModeProperty::Pointer renderingModeProperty =
613  node->SetProperty("Image Rendering.Mode", renderingModeProperty, renderer);
614 
615  mitk::LevelWindow levelwindow(32767.5, 65535);
617 
618  levWinProp->SetLevelWindow(levelwindow);
619  node->SetProperty("levelwindow", levWinProp, renderer);
620 
621  node->SetProperty("labelset.contour.active", BoolProperty::New(true), renderer);
622  node->SetProperty("labelset.contour.width", FloatProperty::New(2.0), renderer);
623 
624  Superclass::SetDefaultProperties(node, renderer, overwrite);
625 }
626 
628 {
629 }
630 
632 {
633  // Do as much actions as possible in here to avoid double executions.
634  m_Plane = vtkSmartPointer<vtkPlaneSource>::New();
635  m_Actors = vtkSmartPointer<vtkPropAssembly>::New();
636  m_OutlinePolyData = vtkSmartPointer<vtkPolyData>::New();
637  m_EmptyPolyData = vtkSmartPointer<vtkPolyData>::New();
638  m_OutlineActor = vtkSmartPointer<vtkActor>::New();
639  m_OutlineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
640  m_OutlineShadowActor = vtkSmartPointer<vtkActor>::New();
641 
642  m_NumberOfLayers = 0;
643  m_mmPerPixel = nullptr;
644 
645  m_OutlineActor->SetMapper(m_OutlineMapper);
646  m_OutlineShadowActor->SetMapper(m_OutlineMapper);
647 
648  m_OutlineActor->SetVisibility(false);
649  m_OutlineShadowActor->SetVisibility(false);
650 }
virtual ScalarType SignedDistance(const Point3D &pt3d_mm) const
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.
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 void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=nullptr, bool overwrite=false)
Set the default properties for general image rendering.
static Pointer New()
vtkRenderer * GetVtkRenderer() const
LocalStorage()
Default constructor of the local storage.
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
double ScalarType
void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
Does the actual resampling, without rendering the image yet. All the data is generated inside this me...
vtkSmartPointer< vtkActor > m_OutlineActor
An actor for the outline.
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...
std::vector< vtkSmartPointer< vtkActor > > m_LayerActorVector
bool GetFloatProperty(const char *propertyKey, float &floatValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for float properties (instances of FloatProperty)
Organizes the rendering process.
bool RenderingGeometryIntersectsImage(const PlaneGeometry *renderingGeometry, SlicedGeometry3D *imageGeometry)
Calculates whether the given rendering geometry intersects the given SlicedGeometry3D.
vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
static Pointer New()
itk::TimeStamp m_LastPropertyUpdateTime
Timestamp of last update of a property.
A data structure describing a label.
Definition: mitkLabel.h:31
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
std::vector< vtkSmartPointer< vtkImageData > > m_ReslicedImageVector
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)
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
std::vector< vtkSmartPointer< vtkMitkLevelWindowFilter > > m_LevelWindowFilterVector
This filter is used to apply the level window to Grayvalue and RBG(A) images.
float CalculateLayerDepth(mitk::BaseRenderer *renderer)
This method uses the vtkCamera clipping range and the layer property to calcualte the depth of the ob...
bool GetVisible() const
Definition: mitkLabel.cpp:121
The LevelWindow class Class to store level/window values.
void Update(mitk::BaseRenderer *renderer) override
Checks whether this mapper needs to update itself and generate data.
static Pointer New()
~LocalStorage() override
Default deconstructor of the local storage.
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
LocalStorage * GetLocalStorage(mitk::BaseRenderer *renderer)
Get the LocalStorage corresponding to the current renderer.
mitk::LocalStorageHandler< LocalStorage > m_LSH
The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
#define MITK_WARN
Definition: mitkLogMacros.h:19
void ApplyOpacity(mitk::BaseRenderer *renderer, int layer)
Set the opacity of the actor.
vtkSmartPointer< vtkActor > m_OutlineShadowActor
An actor for the outline shadow.
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
mitk::ScalarType * m_mmPerPixel
mmPerPixel relation between pixel and mm. (World spacing).
const mitk::Color & GetColor() const
Definition: mitkLabel.cpp:197
virtual void CalculateTimeStep(BaseRenderer *renderer)
Updates the time step, which is sometimes needed in subclasses.
Definition: mitkMapper.cpp:79
void TransformActor(mitk::BaseRenderer *renderer)
Transforms the actor to the actual position in 3D.
mitk::Image::Pointer image
void ApplyColor(mitk::BaseRenderer *renderer, const mitk::Color &color)
Set the color of the image/polydata.
PixelType GetValue() const
Definition: mitkLabel.cpp:169
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
Describes the geometry of a data object consisting of slices.
Internal class holding the mapper, actor, etc. for each of the 3 2D render windows.
static Pointer New()
void ApplyLookuptable(mitk::BaseRenderer *renderer, int layer)
This method applies (or modifies) the lookuptable for all types of images.
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is nullptr, the BaseRenderer-independent PropertyLi...
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
LabelSetImage class for handling labels and layers in a segmentation session.
int GetTimestep() const
Returns the current time step as calculated from the renderer.
Definition: mitkMapper.h:147
unsigned short PixelType
Definition: mitkLabel.h:36
std::vector< vtkSmartPointer< vtkNeverTranslucentTexture > > m_LayerTextureVector
unsigned long GetCurrentWorldPlaneGeometryUpdateTime()
Get timestamp of last call of SetCurrentWorldPlaneGeometry.
Describes a two-dimensional, rectangular plane.
std::vector< mitk::ExtractSliceFilter::Pointer > m_ReslicerVector
std::vector< vtkSmartPointer< vtkPolyDataMapper > > m_LayerMapperVector
vtkSmartPointer< vtkPolyDataMapper > m_OutlineMapper
A mapper for the outline.
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
itk::TimeStamp m_LastDataUpdateTime
Timestamp of last update of stored data.
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
vtkSmartPointer< vtkPolyData > CreateOutlinePolyData(mitk::BaseRenderer *renderer, vtkImageData *image, int pixelValue=1)
Generates a vtkPolyData object containing the outline of a given binary slice.
void GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6])
Generates a plane according to the size of the resliced image in milimeters.