Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.