Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkUnstructuredGridMapper2D.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 
18 #include <mitkGL.h>
19 
21 #include "mitkBaseRenderer.h"
22 #include "mitkColorProperty.h"
23 #include "mitkPlaneGeometry.h"
24 #include "mitkProperties.h"
25 #include "mitkTransferFunction.h"
27 #include "mitkUnstructuredGrid.h"
28 #include "mitkVtkMapper3D.h"
30 
31 #include <vtkAbstractMapper3D.h>
32 #include <vtkAbstractVolumeMapper.h>
33 #include <vtkAssembly.h>
34 #include <vtkCellArray.h>
35 #include <vtkCellData.h>
36 #include <vtkColorTransferFunction.h>
37 #include <vtkLinearTransform.h>
38 #include <vtkLookupTable.h>
39 #include <vtkPiecewiseFunction.h>
40 #include <vtkPlane.h>
41 #include <vtkPointData.h>
42 #include <vtkProp3DCollection.h>
43 #include <vtkScalarsToColors.h>
44 #include <vtkUnstructuredGrid.h>
45 #include <vtkVolume.h>
46 #include <vtkVolumeProperty.h>
47 
48 #include "vtkPointSetSlicer.h"
49 
51 {
52  BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
53  bool needGenerateData = ls->IsGenerateDataRequired(renderer, this, GetDataNode());
54 
55  if (needGenerateData)
56  {
58 
60  if (node.IsNull())
61  return;
62 
63  if (!node->GetProperty(m_ScalarMode, "scalar mode"))
64  {
66  }
67 
68  if (!node->GetProperty(m_ScalarVisibility, "scalar visibility"))
69  {
71  }
72 
73  if (!node->GetProperty(m_Outline, "outline polygons"))
74  {
76  }
77 
78  if (!node->GetProperty(m_Color, "color"))
79  {
80  m_Color = mitk::ColorProperty::New(1.0f, 1.0f, 1.0f);
81  }
82 
83  if (!node->GetProperty(m_LineWidth, "line width"))
84  {
86  }
87  }
88  mitk::BaseData::Pointer input = const_cast<mitk::BaseData *>(GetDataNode()->GetData());
89  assert(input);
90 
91  input->Update();
92 
93  if (m_VtkPointSet)
94  m_VtkPointSet->UnRegister(0);
95  m_VtkPointSet = this->GetVtkPointSet(renderer, this->GetTimestep());
96  assert(m_VtkPointSet);
97  m_VtkPointSet->Register(0);
98 
99  if (m_ScalarVisibility->GetValue())
100  {
103  node->GetProperty(transferFuncProp, "TransferFunction", renderer);
104  if (transferFuncProp.IsNotNull())
105  {
106  mitk::TransferFunction::Pointer tf = transferFuncProp->GetValue();
107  if (m_ScalarsToColors)
108  m_ScalarsToColors->UnRegister(0);
109  m_ScalarsToColors = static_cast<vtkScalarsToColors *>(tf->GetColorTransferFunction());
110  m_ScalarsToColors->Register(0);
111 
112  if (m_ScalarsToOpacity)
113  m_ScalarsToOpacity->UnRegister(0);
114  m_ScalarsToOpacity = tf->GetScalarOpacityFunction();
115  m_ScalarsToOpacity->Register(0);
116  }
117  else
118  {
119  if (m_ScalarsToColors)
120  m_ScalarsToColors->UnRegister(0);
121  m_ScalarsToColors = this->GetVtkLUT(renderer);
122  assert(m_ScalarsToColors);
123  m_ScalarsToColors->Register(0);
124 
125  float opacity;
126  node->GetOpacity(opacity, renderer);
127  if (m_ScalarsToOpacity)
128  m_ScalarsToOpacity->UnRegister(0);
130  double range[2];
131  m_VtkPointSet->GetScalarRange(range);
132  m_ScalarsToOpacity->AddSegment(range[0], opacity, range[1], opacity);
133  }
134  }
135 }
136 
138 {
139  bool visible = true;
140  GetDataNode()->GetVisibility(visible, renderer, "visible");
141  if (!visible)
142  return;
143 
144  vtkLinearTransform *vtktransform = GetDataNode()->GetVtkTransform();
145  vtkLinearTransform *inversetransform = vtktransform->GetLinearInverse();
146 
147  PlaneGeometry::ConstPointer worldGeometry = renderer->GetCurrentWorldPlaneGeometry();
148  PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast<const PlaneGeometry *>(worldGeometry.GetPointer());
149 
150  Point3D point;
151  Vector3D normal;
152 
153  if (worldPlaneGeometry.IsNotNull())
154  {
155  // set up vtkPlane according to worldGeometry
156  point = worldPlaneGeometry->GetOrigin();
157  normal = worldPlaneGeometry->GetNormal();
158  normal.Normalize();
159  m_Plane->SetTransform((vtkAbstractTransform *)NULL);
160  }
161  else
162  {
163  //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "plane plane" into a "curved
164  //plane"?
165  return;
166  AbstractTransformGeometry::ConstPointer worldAbstractGeometry =
167  dynamic_cast<const AbstractTransformGeometry *>(renderer->GetCurrentWorldPlaneGeometry());
168  if (worldAbstractGeometry.IsNotNull())
169  {
170  // set up vtkPlane according to worldGeometry
171  point = const_cast<mitk::BoundingBox *>(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum();
172  FillVector3D(normal, 0, 0, 1);
173  m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse());
174  }
175  else
176  return;
177  }
178 
179  double vp[3], vnormal[3];
180 
181  vnl2vtk(point.GetVnlVector(), vp);
182  vnl2vtk(normal.GetVnlVector(), vnormal);
183 
184  // normally, we would need to transform the surface and cut the transformed surface with the cutter.
185  // This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead.
186  //@todo It probably does not work for scaling operations yet:scaling operations have to be
187  // dealed with after the cut is performed by scaling the contour.
188  inversetransform->TransformPoint(vp, vp);
189  inversetransform->TransformNormalAtPoint(vp, vnormal, vnormal);
190 
191  m_Plane->SetOrigin(vp);
192  m_Plane->SetNormal(vnormal);
193 
194  // set data into cutter
195  m_Slicer->SetInputData(m_VtkPointSet);
196  // m_Cutter->GenerateCutScalarsOff();
197  // m_Cutter->SetSortByToSortByCell();
198 
199  // calculate the cut
200  m_Slicer->Update();
201 
202  // apply color and opacity read from the PropertyList
203  ApplyColorAndOpacityProperties(renderer);
204 
205  // traverse the cut contour
206  vtkPolyData *contour = m_Slicer->GetOutput();
207 
208  vtkPoints *vpoints = contour->GetPoints();
209  vtkCellArray *vlines = contour->GetLines();
210  vtkCellArray *vpolys = contour->GetPolys();
211  vtkPointData *vpointdata = contour->GetPointData();
212  vtkDataArray *vscalars = vpointdata->GetScalars();
213 
214  vtkCellData *vcelldata = contour->GetCellData();
215  vtkDataArray *vcellscalars = vcelldata->GetScalars();
216 
217  const int numberOfLines = contour->GetNumberOfLines();
218  const int numberOfPolys = contour->GetNumberOfPolys();
219 
220  const bool useCellData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT ||
221  m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA;
222  const bool usePointData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA;
223 
224  Point3D p;
225  Point2D p2d;
226 
227  vlines->InitTraversal();
228  vpolys->InitTraversal();
229 
230  mitk::Color outlineColor = m_Color->GetColor();
231 
232  glLineWidth((float)m_LineWidth->GetValue());
233 
234  for (int i = 0; i < numberOfLines; ++i)
235  {
236  vtkIdType *cell(0);
237  vtkIdType cellSize(0);
238 
239  vlines->GetNextCell(cellSize, cell);
240 
241  float rgba[4] = {outlineColor[0], outlineColor[1], outlineColor[2], 1.0f};
242  if (m_ScalarVisibility->GetValue() && vcellscalars)
243  {
244  if (useCellData)
245  { // color each cell according to cell data
246  double scalar = vcellscalars->GetComponent(i, 0);
247  double rgb[3] = {1.0f, 1.0f, 1.0f};
248  m_ScalarsToColors->GetColor(scalar, rgb);
249  rgba[0] = (float)rgb[0];
250  rgba[1] = (float)rgb[1];
251  rgba[2] = (float)rgb[2];
252  rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
253  }
254  else if (usePointData)
255  {
256  double scalar = vscalars->GetComponent(i, 0);
257  double rgb[3] = {1.0f, 1.0f, 1.0f};
258  m_ScalarsToColors->GetColor(scalar, rgb);
259  rgba[0] = (float)rgb[0];
260  rgba[1] = (float)rgb[1];
261  rgba[2] = (float)rgb[2];
262  rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
263  }
264  }
265 
266  glColor4fv(rgba);
267 
268  glBegin(GL_LINE_LOOP);
269  for (int j = 0; j < cellSize; ++j)
270  {
271  vpoints->GetPoint(cell[j], vp);
272  // take transformation via vtktransform into account
273  vtktransform->TransformPoint(vp, vp);
274 
275  vtk2itk(vp, p);
276 
277  // convert 3D point (in mm) to display coordinates (units )
278  renderer->WorldToDisplay(p, p2d);
279 
280  // convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left )
281  // p2d[1]=toGL-p2d[1];
282 
283  // add the current vertex to the line
284  glVertex2f(p2d[0], p2d[1]);
285  }
286  glEnd();
287  }
288 
289  bool polyOutline = m_Outline->GetValue();
290  bool scalarVisibility = m_ScalarVisibility->GetValue();
291 
292  // cache the transformed points
293  // a fixed size array is way faster than 'new'
294  // slices through 3d cells usually do not generated
295  // polygons with more than 6 vertices
296  const int maxPolySize = 10;
297  Point2D *cachedPoints = new Point2D[maxPolySize * numberOfPolys];
298 
299  glEnable(GL_BLEND);
300  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
301 
302  // only draw polygons if there are cell scalars
303  // or the outline property is set to true
304  if (scalarVisibility && vcellscalars)
305  {
306  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
307 
308  for (int i = 0; i < numberOfPolys; ++i)
309  {
310  vtkIdType *cell(0);
311  vtkIdType cellSize(0);
312 
313  vpolys->GetNextCell(cellSize, cell);
314 
315  float rgba[4] = {1.0f, 1.0f, 1.0f, 0};
316  if (scalarVisibility && vcellscalars)
317  {
318  if (useCellData)
319  { // color each cell according to cell data
320  double scalar = vcellscalars->GetComponent(i + numberOfLines, 0);
321  double rgb[3] = {1.0f, 1.0f, 1.0f};
322  m_ScalarsToColors->GetColor(scalar, rgb);
323  rgba[0] = (float)rgb[0];
324  rgba[1] = (float)rgb[1];
325  rgba[2] = (float)rgb[2];
326  rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
327  }
328  else if (usePointData)
329  {
330  double scalar = vscalars->GetComponent(i, 0);
331  double rgb[3] = {1.0f, 1.0f, 1.0f};
332  m_ScalarsToColors->GetColor(scalar, rgb);
333  rgba[0] = (float)rgb[0];
334  rgba[1] = (float)rgb[1];
335  rgba[2] = (float)rgb[2];
336  rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar);
337  }
338  }
339  glColor4fv(rgba);
340 
341  glBegin(GL_POLYGON);
342  for (int j = 0; j < cellSize; ++j)
343  {
344  vpoints->GetPoint(cell[j], vp);
345  // take transformation via vtktransform into account
346  vtktransform->TransformPoint(vp, vp);
347 
348  vtk2itk(vp, p);
349 
350  // convert 3D point (in mm) to display coordinates (units )
351  renderer->WorldToDisplay(p, p2d);
352 
353  // convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left )
354  // p2d[1]=toGL-p2d[1];
355 
356  cachedPoints[i * 10 + j][0] = p2d[0];
357  cachedPoints[i * 10 + j][1] = p2d[1];
358 
359  // add the current vertex to the line
360  glVertex2f(p2d[0], p2d[1]);
361  }
362  glEnd();
363  }
364 
365  if (polyOutline)
366  {
367  vpolys->InitTraversal();
368 
369  glColor4f(outlineColor[0], outlineColor[1], outlineColor[2], 1.0f);
370  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
371  for (int i = 0; i < numberOfPolys; ++i)
372  {
373  vtkIdType *cell(0);
374  vtkIdType cellSize(0);
375 
376  vpolys->GetNextCell(cellSize, cell);
377 
378  glBegin(GL_POLYGON);
379  // glPolygonOffset(1.0, 1.0);
380  for (int j = 0; j < cellSize; ++j)
381  {
382  // add the current vertex to the line
383  glVertex2f(cachedPoints[i * 10 + j][0], cachedPoints[i * 10 + j][1]);
384  }
385  glEnd();
386  }
387  }
388  }
389  glDisable(GL_BLEND);
390  delete[] cachedPoints;
391 }
392 
394 {
395  // MITK_INFO << "GETVTKABSTRACTMAPPER3D\n";
396  mitk::DataNode::ConstPointer node = this->GetDataNode();
397  if (node.IsNull())
398  return 0;
399 
400  mitk::VtkMapper::Pointer mitkMapper = dynamic_cast<mitk::VtkMapper *>(node->GetMapper(2));
401  if (mitkMapper.IsNull())
402  {
403  return 0;
404  }
405 
406  mitkMapper->Update(renderer);
407 
408  vtkAssembly *assembly = dynamic_cast<vtkAssembly *>(mitkMapper->GetVtkProp(renderer));
409  if (assembly)
410  {
411  vtkProp3DCollection *collection = assembly->GetParts();
412  collection->InitTraversal();
413  vtkProp3D *prop3d = 0;
414  do
415  {
416  prop3d = collection->GetNextProp3D();
417  vtkActor *actor = dynamic_cast<vtkActor *>(prop3d);
418  if (actor)
419  {
420  return dynamic_cast<vtkAbstractMapper3D *>(actor->GetMapper());
421  }
422 
423  vtkVolume *volume = dynamic_cast<vtkVolume *>(prop3d);
424  if (volume)
425  {
426  return dynamic_cast<vtkAbstractMapper3D *>(volume->GetMapper());
427  }
428  } while (prop3d != collection->GetLastProp3D());
429  }
430  else
431  {
432  vtkActor *actor = dynamic_cast<vtkActor *>(mitkMapper->GetVtkProp(renderer));
433  if (actor)
434  {
435  return dynamic_cast<vtkAbstractMapper3D *>(actor->GetMapper());
436  }
437 
438  vtkVolume *volume = dynamic_cast<vtkVolume *>(mitkMapper->GetVtkProp(renderer));
439  if (volume)
440  {
441  return dynamic_cast<vtkAbstractMapper3D *>(volume->GetMapper());
442  }
443  }
444  return 0;
445 }
446 
448 {
449  // MITK_INFO << "GETVTKPOINTSET\n";
450  vtkAbstractMapper3D *abstractMapper = GetVtkAbstractMapper3D(renderer);
451  if (abstractMapper == 0)
452  {
453  // try to get data from the node
454  mitk::DataNode::ConstPointer node = this->GetDataNode();
455  if (node.IsNull())
456  return 0;
457  mitk::BaseData::Pointer data = node->GetData();
458  mitk::UnstructuredGrid::Pointer grid = dynamic_cast<mitk::UnstructuredGrid *>(data.GetPointer());
459  if (!grid.IsNull())
460  return static_cast<vtkPointSet *>(grid->GetVtkUnstructuredGrid(time));
461 
462  return 0;
463  }
464  else
465  {
466  vtkMapper *mapper = dynamic_cast<vtkMapper *>(abstractMapper);
467  if (mapper)
468  {
469  return dynamic_cast<vtkPointSet *>(mapper->GetInput());
470  }
471  vtkAbstractVolumeMapper *volMapper = dynamic_cast<vtkAbstractVolumeMapper *>(abstractMapper);
472  if (volMapper)
473  {
474  return dynamic_cast<vtkPointSet *>(volMapper->GetDataSetInput());
475  }
476  }
477 
478  return 0;
479 }
480 
482 {
483  // MITK_INFO << "GETVTKLUT\n";
484  vtkMapper *mapper = dynamic_cast<vtkMapper *>(GetVtkAbstractMapper3D(renderer));
485  if (mapper)
486  return mapper->GetLookupTable();
487  else
488  {
489  mitk::DataNode::ConstPointer node = this->GetDataNode();
490  if (node.IsNull())
491  return 0;
492 
493  mitk::VtkMapper::Pointer mitkMapper = dynamic_cast<mitk::VtkMapper *>(node->GetMapper(2));
494  if (mitkMapper.IsNull())
495  {
496  // MITK_INFO << "mitkMapper is null\n";
497  return 0;
498  }
499 
500  mitkMapper->Update(renderer);
501 
502  vtkVolume *volume = dynamic_cast<vtkVolume *>(mitkMapper->GetVtkProp(renderer));
503  if (volume)
504  {
505  // MITK_INFO << "found volume prop\n";
506  return static_cast<vtkScalarsToColors *>(volume->GetProperty()->GetRGBTransferFunction());
507  }
508 
509  vtkAssembly *assembly = dynamic_cast<vtkAssembly *>(mitkMapper->GetVtkProp(renderer));
510  if (assembly)
511  {
512  // MITK_INFO << "found assembly prop\n";
514  node->GetProperty(transferFuncProp, "TransferFunction", 0);
515  if (transferFuncProp.IsNotNull())
516  {
517  MITK_INFO << "return colortransferfunction\n";
518  return static_cast<vtkScalarsToColors *>(transferFuncProp->GetValue()->GetColorTransferFunction());
519  }
520  }
521  return 0;
522  }
523 }
524 
526 {
527  return (GetVtkPointSet(renderer, this->GetTimestep()) != 0);
528 }
529 
531 {
532  m_Plane = vtkPlane::New();
533  m_Slicer = vtkPointSetSlicer::New();
534 
535  m_Slicer->SetSlicePlane(m_Plane);
536 
537  m_ScalarsToColors = 0;
538  m_ScalarsToOpacity = 0;
539  m_VtkPointSet = 0;
540 
541  // m_LUT = vtkLookupTable::New();
542  // m_LUT->SetTableRange( 0, 255 );
543  // m_LUT->SetNumberOfColors( 255 );
544  // m_LUT->SetRampToLinear ();
545  // m_LUT->Build();
546 }
547 
549 {
550  m_Slicer->Delete();
551  m_Plane->Delete();
552 
553  if (m_ScalarsToOpacity != 0)
554  m_ScalarsToOpacity->UnRegister(0);
555  if (m_ScalarsToColors != 0)
556  m_ScalarsToColors->UnRegister(0);
557  if (m_VtkPointSet != 0)
558  m_VtkPointSet->UnRegister(0);
559 }
itk::BoundingBox< unsigned long, 3, ScalarType > BoundingBox
Standard 3D-BoundingBox typedef.
L * GetLocalStorage(mitk::BaseRenderer *forRenderer)
Retrieves a LocalStorage for a specific BaseRenderer.
Base class for mapper specific rendering ressources.
Definition: mitkMapper.h:200
virtual void GenerateDataForRenderer(BaseRenderer *) override
Generate the data needed for rendering into renderer.
#define MITK_INFO
Definition: mitkLogMacros.h:22
Base of all data objects.
Definition: mitkBaseData.h:39
LocalStorageHandler< BaseLocalStorage > m_LSH
static Pointer New()
Organizes the rendering process.
mitk::BoolProperty::Pointer m_ScalarVisibility
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual vtkScalarsToColors * GetVtkLUT(BaseRenderer *renderer)
Base class of all Vtk Mappers in order to display primitives by exploiting Vtk functionality.
Definition: mitkVtkMapper.h:53
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:110
int GetTimestep() const
Returns the current time step as calculated from the renderer.
Definition: mitkMapper.h:152
static Pointer New()
void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const
This method converts a 3D world index to the display point using the geometry of the renderWindow...
bool IsGenerateDataRequired(mitk::BaseRenderer *renderer, mitk::Mapper *mapper, mitk::DataNode *dataNode) const
Definition: mitkMapper.cpp:129
mitk::VtkScalarModeProperty::Pointer m_ScalarMode
virtual vtkAbstractMapper3D * GetVtkAbstractMapper3D(BaseRenderer *renderer)
void vnl2vtk(const vnl_vector< Tin > &in, Tout *out)
void vtk2itk(const Tin &in, Tout &out)
Describes a geometry defined by an vtkAbstractTransform and a plane.
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
static Pointer New()
static vtkPointSetSlicer * New()
virtual bool IsConvertibleToVtkPointSet(BaseRenderer *renderer)
virtual vtkPointSet * GetVtkPointSet(BaseRenderer *renderer, int time=0)
Class for storing unstructured grids (vtkUnstructuredGrid)
Describes a two-dimensional, rectangular plane.
virtual DataNode * GetDataNode() const
Get the DataNode containing the data to map. Method only returns valid DataNode Pointer if the mapper...
Definition: mitkMapper.cpp:36
virtual void Paint(mitk::BaseRenderer *renderer) override
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.