Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
vtkMitkGPUVolumeRayCastMapper.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 
18  Program: Visualization Toolkit
19  Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.cxx,v $
20 
21  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
22  All rights reserved.
23  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
24 
25  This software is distributed WITHOUT ANY WARRANTY; without even
26  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
27  PURPOSE. See the above copyright notice for more information.
28 
29 =========================================================================*/
30 
32 
33 // Only with VTK 5.6 or above
34 #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6)))
35 
36 #include "vtkCamera.h"
37 #include "vtkCellData.h"
38 #include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event
39 #include "vtkDataArray.h"
40 #include "vtkGPUInfo.h"
41 #include "vtkGPUInfoList.h"
42 #include "vtkImageData.h"
43 #include "vtkImageResample.h"
44 #include "vtkMultiThreader.h"
45 #include "vtkPointData.h"
46 #include "vtkRenderWindow.h"
47 #include "vtkRenderer.h"
48 #include "vtkRendererCollection.h"
49 #include "vtkTimerLog.h"
50 #include "vtkVolume.h"
51 #include "vtkVolumeProperty.h"
52 #include <assert.h>
53 
54 vtkInstantiatorNewMacro(vtkMitkGPUVolumeRayCastMapper);
55 vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, MaskInput, vtkImageData);
56 vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, TransformedInput, vtkImageData);
57 
58 vtkMitkGPUVolumeRayCastMapper::vtkMitkGPUVolumeRayCastMapper()
59 {
60  this->AutoAdjustSampleDistances = 1;
61  this->ImageSampleDistance = 1.0;
62  this->MinimumImageSampleDistance = 1.0;
63  this->MaximumImageSampleDistance = 10.0;
64  this->SampleDistance = 1.0;
65  this->SmallVolumeRender = 0;
66  this->BigTimeToDraw = 0.0;
67  this->SmallTimeToDraw = 0.0;
68  this->FinalColorWindow = 1.0;
69  this->FinalColorLevel = 0.5;
70  this->GeneratingCanonicalView = 0;
71  this->CanonicalViewImageData = nullptr;
72 
73  this->MaskInput = nullptr;
74  this->MaskBlendFactor = 1.0f;
75 
76  this->AMRMode = 0;
77  this->ClippedCroppingRegionPlanes[0] = VTK_DOUBLE_MAX;
78  this->ClippedCroppingRegionPlanes[1] = VTK_DOUBLE_MIN;
79  this->ClippedCroppingRegionPlanes[2] = VTK_DOUBLE_MAX;
80  this->ClippedCroppingRegionPlanes[3] = VTK_DOUBLE_MIN;
81  this->ClippedCroppingRegionPlanes[4] = VTK_DOUBLE_MAX;
82  this->ClippedCroppingRegionPlanes[5] = VTK_DOUBLE_MIN;
83 
84  this->MaxMemoryInBytes = 0;
85  vtkGPUInfoList *l = vtkGPUInfoList::New();
86  l->Probe();
87  if (l->GetNumberOfGPUs() > 0)
88  {
89  vtkGPUInfo *info = l->GetGPUInfo(0);
90  this->MaxMemoryInBytes = info->GetDedicatedVideoMemory();
91  if (this->MaxMemoryInBytes == 0)
92  {
93  this->MaxMemoryInBytes = info->GetDedicatedSystemMemory();
94  }
95  // we ignore info->GetSharedSystemMemory(); as this is very slow.
96  }
97  l->Delete();
98 
99  if (this->MaxMemoryInBytes == 0) // use some default value: 128MB.
100  {
101  this->MaxMemoryInBytes = 128 * 1024 * 1024;
102  }
103 
104  this->MaxMemoryFraction = 0.75;
105 
106  this->ReportProgress = true;
107 
108  this->TransformedInput = nullptr;
109  this->LastInput = nullptr;
110 }
111 
112 // ----------------------------------------------------------------------------
113 vtkMitkGPUVolumeRayCastMapper::~vtkMitkGPUVolumeRayCastMapper()
114 {
115  this->SetMaskInput(nullptr);
116  this->SetTransformedInput(nullptr);
117  this->LastInput = nullptr;
118 }
119 
120 // ----------------------------------------------------------------------------
121 // The render method that is called from the volume. If this is a canonical
122 // view render, a specialized version of this method will be called instead.
123 // Otherwise we will
124 // - Invoke a start event
125 // - Start timing
126 // - Check that everything is OK for rendering
127 // - Render
128 // - Stop the timer and record results
129 // - Invoke an end event
130 // ----------------------------------------------------------------------------
131 void vtkMitkGPUVolumeRayCastMapper::Render(vtkRenderer *ren, vtkVolume *vol)
132 {
133  // Catch renders that are happening due to a canonical view render and
134  // handle them separately.
135  if (this->GeneratingCanonicalView)
136  {
137  this->CanonicalViewRender(ren, vol);
138  return;
139  }
140 
141  // Invoke a VolumeMapperRenderStartEvent
142  this->InvokeEvent(vtkCommand::VolumeMapperRenderStartEvent, nullptr);
143 
144  // Start the timer to time the length of this render
145  vtkTimerLog *timer = vtkTimerLog::New();
146  timer->StartTimer();
147 
148  // Make sure everything about this render is OK.
149  // This is where the input is updated.
150  if (this->ValidateRender(ren, vol))
151  {
152  // Everything is OK - so go ahead and really do the render
153  this->GPURender(ren, vol);
154  }
155 
156  // Stop the timer
157  timer->StopTimer();
158  double t = timer->GetElapsedTime();
159 
160  // cout << "Render Timer " << t << " seconds, " << 1.0/t << " frames per second" << endl;
161 
162  this->TimeToDraw = t;
163  timer->Delete();
164 
165  if (vol->GetAllocatedRenderTime() < 1.0)
166  {
167  this->SmallTimeToDraw = t;
168  }
169  else
170  {
171  this->BigTimeToDraw = t;
172  }
173 
174  // Invoke a VolumeMapperRenderEndEvent
175  this->InvokeEvent(vtkCommand::VolumeMapperRenderEndEvent, nullptr);
176 }
177 
178 // ----------------------------------------------------------------------------
179 // Special version for rendering a canonical view - we don't do things like
180 // invoke start or end events, and we don't capture the render time.
181 // ----------------------------------------------------------------------------
182 void vtkMitkGPUVolumeRayCastMapper::CanonicalViewRender(vtkRenderer *ren, vtkVolume *vol)
183 {
184  // Make sure everything about this render is OK
185  if (this->ValidateRender(ren, vol))
186  {
187  // Everything is OK - so go ahead and really do the render
188  this->GPURender(ren, vol);
189  }
190 }
191 
192 // ----------------------------------------------------------------------------
193 // This method us used by the render method to validate everything before
194 // attempting to render. This method returns 0 if something is not right -
195 // such as missing input, a null renderer or a null volume, no scalars, etc.
196 // In some cases it will produce a vtkErrorMacro message, and in others
197 // (for example, in the case of cropping planes that define a region with
198 // a volume or 0 or less) it will fail silently. If everything is OK, it will
199 // return with a value of 1.
200 // ----------------------------------------------------------------------------
201 int vtkMitkGPUVolumeRayCastMapper::ValidateRender(vtkRenderer *ren, vtkVolume *vol)
202 {
203  // Check that we have everything we need to render.
204  int goodSoFar = 1;
205 
206  // Check for a renderer - we MUST have one
207  if (!ren)
208  {
209  goodSoFar = 0;
210  vtkErrorMacro("Renderer cannot be null.");
211  }
212 
213  // Check for the volume - we MUST have one
214  if (goodSoFar && !vol)
215  {
216  goodSoFar = 0;
217  vtkErrorMacro("Volume cannot be null.");
218  }
219 
220  // Don't need to check if we have a volume property
221  // since the volume will create one if we don't. Also
222  // don't need to check for the scalar opacity function
223  // or the RGB transfer function since the property will
224  // create them if they do not yet exist.
225 
226  // However we must currently check that the number of
227  // color channels is 3
228  // TODO: lift this restriction - should work with
229  // gray functions as well. Right now turning off test
230  // because otherwise 4 component rendering isn't working.
231  // Will revisit.
232  if (goodSoFar && vol->GetProperty()->GetColorChannels() != 3)
233  {
234  // goodSoFar = 0;
235  // vtkErrorMacro("Must have a color transfer function.");
236  }
237 
238  // Check the cropping planes. If they are invalid, just silently
239  // fail. This will happen when an interactive widget is dragged
240  // such that it defines 0 or negative volume - this can happen
241  // and should just not render the volume.
242  // Check the cropping planes
243  if (goodSoFar && this->Cropping && (this->CroppingRegionPlanes[0] >= this->CroppingRegionPlanes[1] ||
244  this->CroppingRegionPlanes[2] >= this->CroppingRegionPlanes[3] ||
245  this->CroppingRegionPlanes[4] >= this->CroppingRegionPlanes[5]))
246  {
247  // No error message here - we want to be silent
248  goodSoFar = 0;
249  }
250 
251  // Check that we have input data
252  vtkImageData *input = this->GetInput();
253 
254  // If we have a timestamp change or data change then create a new clone.
255  if (input != this->LastInput || input->GetMTime() > this->TransformedInput->GetMTime())
256  {
257  this->LastInput = input;
258 
259  vtkImageData *clone;
260  if (!this->TransformedInput)
261  {
262  clone = vtkImageData::New();
263  this->SetTransformedInput(clone);
264  clone->Delete();
265  }
266  else
267  {
268  clone = this->TransformedInput;
269  }
270 
271  clone->ShallowCopy(input);
272 
273  // @TODO: This is the workaround to deal with GPUVolumeRayCastMapper
274  // not able to handle extents starting from non zero values.
275  // There is not a easy fix in the GPU volume ray cast mapper hence
276  // this fix has been introduced.
277 
278  // Get the current extents.
279  int extents[6], real_extents[6];
280  clone->GetExtent(extents);
281  clone->GetExtent(real_extents);
282 
283  // Get the current origin and spacing.
284  double origin[3], spacing[3];
285  clone->GetOrigin(origin);
286  clone->GetSpacing(spacing);
287 
288  for (int cc = 0; cc < 3; cc++)
289  {
290  // Transform the origin and the extents.
291  origin[cc] = origin[cc] + extents[2 * cc] * spacing[cc];
292  extents[2 * cc + 1] -= extents[2 * cc];
293  extents[2 * cc] -= extents[2 * cc];
294  }
295 
296  clone->SetOrigin(origin);
297  clone->SetExtent(extents);
298  }
299 
300  if (goodSoFar && !this->TransformedInput)
301  {
302  vtkErrorMacro("Input is NULL but is required");
303  goodSoFar = 0;
304  }
305 
306  // Update the date then make sure we have scalars. Note
307  // that we must have point or cell scalars because field
308  // scalars are not supported.
309  vtkDataArray *scalars = nullptr;
310  if (goodSoFar)
311  {
312  // Here is where we update the input
313  // this->TransformedInput->UpdateInformation(); //VTK6_TODO
314  // this->TransformedInput->SetUpdateExtentToWholeExtent();
315  // this->TransformedInput->Update();
316 
317  // Now make sure we can find scalars
318  scalars = this->GetScalars(
319  this->TransformedInput, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag);
320 
321  // We couldn't find scalars
322  if (!scalars)
323  {
324  vtkErrorMacro("No scalars found on input.");
325  goodSoFar = 0;
326  }
327  // Even if we found scalars, if they are field data scalars that isn't good
328  else if (this->CellFlag == 2)
329  {
330  vtkErrorMacro("Only point or cell scalar support - found field scalars instead.");
331  goodSoFar = 0;
332  }
333  }
334 
335  // Make sure the scalar type is actually supported. This mappers supports
336  // almost all standard scalar types.
337  if (goodSoFar)
338  {
339  switch (scalars->GetDataType())
340  {
341  case VTK_CHAR:
342  vtkErrorMacro(<< "scalar of type VTK_CHAR is not supported "
343  << "because this type is platform dependent. "
344  << "Use VTK_SIGNED_CHAR or VTK_UNSIGNED_CHAR instead.");
345  goodSoFar = 0;
346  break;
347  case VTK_BIT:
348  vtkErrorMacro("scalar of type VTK_BIT is not supported by this mapper.");
349  goodSoFar = 0;
350  break;
351  case VTK_ID_TYPE:
352  vtkErrorMacro("scalar of type VTK_ID_TYPE is not supported by this mapper.");
353  goodSoFar = 0;
354  break;
355  case VTK_STRING:
356  vtkErrorMacro("scalar of type VTK_STRING is not supported by this mapper.");
357  goodSoFar = 0;
358  break;
359  default:
360  // Don't need to do anything here
361  break;
362  }
363  }
364 
365  // Check on the blending type - we support composite and min / max intensity
366  if (goodSoFar)
367  {
368  if (this->BlendMode != vtkVolumeMapper::COMPOSITE_BLEND &&
369  this->BlendMode != vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND &&
370  this->BlendMode != vtkVolumeMapper::MINIMUM_INTENSITY_BLEND)
371  {
372  goodSoFar = 0;
373  vtkErrorMacro(<< "Selected blend mode not supported. "
374  << "Only Composite and MIP and MinIP modes "
375  << "are supported by the current implementation.");
376  }
377  }
378 
379  // This mapper supports 1 component data, or 4 component if it is not independent
380  // component (i.e. the four components define RGBA)
381  int numberOfComponents = 0;
382  if (goodSoFar)
383  {
384  numberOfComponents = scalars->GetNumberOfComponents();
385  if (!(numberOfComponents == 1 || (numberOfComponents == 4 && vol->GetProperty()->GetIndependentComponents() == 0)))
386  {
387  goodSoFar = 0;
388  vtkErrorMacro(<< "Only one component scalars, or four "
389  << "component with non-independent components, "
390  << "are supported by this mapper.");
391  }
392  }
393 
394  // If this is four component data, then it better be unsigned char (RGBA).
395  if (goodSoFar && numberOfComponents == 4 && scalars->GetDataType() != VTK_UNSIGNED_CHAR)
396  {
397  goodSoFar = 0;
398  vtkErrorMacro("Only unsigned char is supported for 4-component scalars!");
399  }
400 
401  // return our status
402  return goodSoFar;
403 }
404 
405 // ----------------------------------------------------------------------------
406 // Description:
407 // Called by the AMR Volume Mapper.
408 // Set the flag that tells if the scalars are on point data (0) or
409 // cell data (1).
410 void vtkMitkGPUVolumeRayCastMapper::SetCellFlag(int cellFlag)
411 {
412  this->CellFlag = cellFlag;
413 }
414 
415 // ----------------------------------------------------------------------------
416 void vtkMitkGPUVolumeRayCastMapper::CreateCanonicalView(vtkRenderer *ren,
417  vtkVolume *volume,
418  vtkImageData *image,
419  int vtkNotUsed(blend_mode),
420  double viewDirection[3],
421  double viewUp[3])
422 {
423  this->GeneratingCanonicalView = 1;
424  int oldSwap = ren->GetRenderWindow()->GetSwapBuffers();
425  ren->GetRenderWindow()->SwapBuffersOff();
426 
427  int dim[3];
428  image->GetDimensions(dim);
429  int *size = ren->GetRenderWindow()->GetSize();
430 
431  vtkImageData *bigImage = vtkImageData::New();
432  bigImage->SetDimensions(size[0], size[1], 1);
433  bigImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
434 
435  this->CanonicalViewImageData = bigImage;
436 
437  double scale[2];
438  scale[0] = dim[0] / static_cast<double>(size[0]);
439  scale[1] = dim[1] / static_cast<double>(size[1]);
440 
441  // Save the visibility flags of the renderers and set all to false except
442  // for the ren.
443  vtkRendererCollection *renderers = ren->GetRenderWindow()->GetRenderers();
444  int numberOfRenderers = renderers->GetNumberOfItems();
445 
446  auto rendererVisibilities = new bool[numberOfRenderers];
447  renderers->InitTraversal();
448  int i = 0;
449  while (i < numberOfRenderers)
450  {
451  vtkRenderer *r = renderers->GetNextItem();
452  rendererVisibilities[i] = r->GetDraw() == 1;
453  if (r != ren)
454  {
455  r->SetDraw(false);
456  }
457  ++i;
458  }
459 
460  // Save the visibility flags of the props and set all to false except
461  // for the volume.
462 
463  vtkPropCollection *props = ren->GetViewProps();
464  int numberOfProps = props->GetNumberOfItems();
465 
466  auto propVisibilities = new bool[numberOfProps];
467  props->InitTraversal();
468  i = 0;
469  while (i < numberOfProps)
470  {
471  vtkProp *p = props->GetNextProp();
472  propVisibilities[i] = p->GetVisibility() == 1;
473  if (p != volume)
474  {
475  p->SetVisibility(false);
476  }
477  ++i;
478  }
479 
480  vtkCamera *savedCamera = ren->GetActiveCamera();
481  savedCamera->Modified();
482  vtkCamera *canonicalViewCamera = vtkCamera::New();
483 
484  // Code from vtkFixedPointVolumeRayCastMapper:
485  double *center = volume->GetCenter();
486  double bounds[6];
487  volume->GetBounds(bounds);
488  double d =
489  sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) +
490  (bounds[5] - bounds[4]) * (bounds[5] - bounds[4]));
491 
492  // For now use x distance - need to change this
493  d = bounds[1] - bounds[0];
494 
495  // Set up the camera in parallel
496  canonicalViewCamera->SetFocalPoint(center);
497  canonicalViewCamera->ParallelProjectionOn();
498  canonicalViewCamera->SetPosition(
499  center[0] - d * viewDirection[0], center[1] - d * viewDirection[1], center[2] - d * viewDirection[2]);
500  canonicalViewCamera->SetViewUp(viewUp);
501  canonicalViewCamera->SetParallelScale(d / 2);
502 
503  ren->SetActiveCamera(canonicalViewCamera);
504  ren->GetRenderWindow()->Render();
505 
506  ren->SetActiveCamera(savedCamera);
507  canonicalViewCamera->Delete();
508 
509  // Shrink to image to the desired size
510  vtkImageResample *resample = vtkImageResample::New();
511  resample->SetInputData(bigImage);
512  resample->SetAxisMagnificationFactor(0, scale[0]);
513  resample->SetAxisMagnificationFactor(1, scale[1]);
514  resample->SetAxisMagnificationFactor(2, 1);
515  resample->UpdateWholeExtent();
516 
517  // Copy the pixels over
518  image->DeepCopy(resample->GetOutput());
519 
520  bigImage->Delete();
521  resample->Delete();
522 
523  // Restore the visibility flags of the props
524  props->InitTraversal();
525  i = 0;
526  while (i < numberOfProps)
527  {
528  vtkProp *p = props->GetNextProp();
529  p->SetVisibility(propVisibilities[i]);
530  ++i;
531  }
532 
533  delete[] propVisibilities;
534 
535  // Restore the visibility flags of the renderers
536  renderers->InitTraversal();
537  i = 0;
538  while (i < numberOfRenderers)
539  {
540  vtkRenderer *r = renderers->GetNextItem();
541  r->SetDraw(rendererVisibilities[i]);
542  ++i;
543  }
544 
545  delete[] rendererVisibilities;
546 
547  ren->GetRenderWindow()->SetSwapBuffers(oldSwap);
548  this->CanonicalViewImageData = nullptr;
549  this->GeneratingCanonicalView = 0;
550 }
551 
552 // ----------------------------------------------------------------------------
553 // Print method for vtkMitkGPUVolumeRayCastMapper
554 void vtkMitkGPUVolumeRayCastMapper::PrintSelf(ostream &os, vtkIndent indent)
555 {
556  this->Superclass::PrintSelf(os, indent);
557 
558  os << indent << "AutoAdjustSampleDistances: " << this->AutoAdjustSampleDistances << endl;
559  os << indent << "MinimumImageSampleDistance: " << this->MinimumImageSampleDistance << endl;
560  os << indent << "MaximumImageSampleDistance: " << this->MaximumImageSampleDistance << endl;
561  os << indent << "ImageSampleDistance: " << this->ImageSampleDistance << endl;
562  os << indent << "SampleDistance: " << this->SampleDistance << endl;
563  os << indent << "FinalColorWindow: " << this->FinalColorWindow << endl;
564  os << indent << "FinalColorLevel: " << this->FinalColorLevel << endl;
565  os << indent << "MaskInput: " << this->MaskInput << endl;
566  os << indent << "MaskBlendFactor: " << this->MaskBlendFactor << endl;
567  os << indent << "MaxMemoryInBytes: " << this->MaxMemoryInBytes << endl;
568  os << indent << "MaxMemoryFraction: " << this->MaxMemoryFraction << endl;
569  os << indent << "ReportProgress: " << this->ReportProgress << endl;
570 }
571 
572 // ----------------------------------------------------------------------------
573 // Description:
574 // Compute the cropping planes clipped by the bounds of the volume.
575 // The result is put into this->ClippedCroppingRegionPlanes.
576 // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage
577 // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes
578 // members instead of CroppingRegionPlanes.
579 // \pre volume_exists: this->GetInput()!=0
580 // \pre valid_cropping: this->Cropping &&
581 // this->CroppingRegionPlanes[0]<this->CroppingRegionPlanes[1] &&
582 // this->CroppingRegionPlanes[2]<this->CroppingRegionPlanes[3] &&
583 // this->CroppingRegionPlanes[4]<this->CroppingRegionPlanes[5])
584 void vtkMitkGPUVolumeRayCastMapper::ClipCroppingRegionPlanes()
585 {
586  assert("pre: volume_exists" && this->GetInput() != nullptr);
587  assert("pre: valid_cropping" && this->Cropping && this->CroppingRegionPlanes[0] < this->CroppingRegionPlanes[1] &&
588  this->CroppingRegionPlanes[2] < this->CroppingRegionPlanes[3] &&
589  this->CroppingRegionPlanes[4] < this->CroppingRegionPlanes[5]);
590 
591  // vtkVolumeMapper::Render() will have something like:
592  // if(this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] ||
593  // this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] ||
594  // this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5]))
595  // {
596  // // silentely stop because the cropping is not valid.
597  // return;
598  // }
599 
600  double volBounds[6];
601  this->GetInput()->GetBounds(volBounds);
602 
603  int i = 0;
604  while (i < 6)
605  {
606  // max of the mins
607  if (this->CroppingRegionPlanes[i] < volBounds[i])
608  {
609  this->ClippedCroppingRegionPlanes[i] = volBounds[i];
610  }
611  else
612  {
613  this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i];
614  }
615  ++i;
616  // min of the maxs
617  if (this->CroppingRegionPlanes[i] > volBounds[i])
618  {
619  this->ClippedCroppingRegionPlanes[i] = volBounds[i];
620  }
621  else
622  {
623  this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i];
624  }
625  ++i;
626  }
627 }
628 
629 #endif
static void info(const char *fmt,...)
Definition: svm.cpp:100
vtkInstantiatorNewMacro(vtkMitkVolumeTextureMapper3D)
static void clone(T *&dst, S *src, int n)
Definition: svm.cpp:73
vtkCxxSetObjectMacro(vtkXMLMaterialParser, Material, vtkXMLMaterial)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.