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
mitkEnhancedPointSetVtkMapper3D.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 
19 //#include <sstream>
20 #include <algorithm>
21 
22 #include "mitkDataNode.h"
23 #include "mitkLookupTables.h"
24 #include "mitkProperties.h"
25 
26 #include "mitkColorProperty.h"
27 //#include "mitkVtkPropRenderer.h"
28 
29 #include <vtkActor.h>
30 
31 #include <vtkAssembly.h>
32 #include <vtkProp3DCollection.h>
33 #include <vtkTubeFilter.h>
34 
35 #include <vtkConeSource.h>
36 #include <vtkCubeSource.h>
37 #include <vtkCylinderSource.h>
38 #include <vtkPolyDataMapper.h>
39 #include <vtkProperty.h>
40 #include <vtkSphereSource.h>
41 #include <vtkTransformPolyDataFilter.h>
42 
43 #include <vtkPolyDataAlgorithm.h>
44 
46 
48 {
49  return static_cast<const mitk::PointSet *>(GetDataNode()->GetData());
50 }
51 
53 {
54  m_Contour = vtkActor::New();
55  m_ContourSource = vtkTubeFilter::New();
56  m_PropAssembly = vtkAssembly::New();
57 }
58 
60 {
61  return m_PropAssembly;
62 }
63 
65 {
66  m_Contour->Delete();
67  m_ContourSource->Delete();
68  m_PropAssembly->Delete();
69 
70  // TODO: do cleanup correctly
71 
72  // Clean up all remaining actors and poly-data sources
73  // std::for_each(m_PointActors.begin(), m_PointActors.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject);
74 
75  // std::for_each(m_SphereSources.begin(), m_SphereSources.end(),
76  // &mitk::EnhancedPointSetVtgkMapper3D::DeleteVtkObject);
77  // std::for_each(m_CubeSources.begin(), m_CubeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject);
78  // std::for_each(m_ConeSources.begin(), m_ConeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject);
79  // std::for_each(m_CylinderSources.begin(), m_CylinderSources.end(),
80  // &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject);
81  //
82 }
83 
85 {
86  // get and update the PointSet
87  const mitk::PointSet *pointset = this->GetInput();
88  // pointset->Update();
89  int timestep = this->GetTimestep();
90 
91  mitk::PointSet::DataType *itkPointSet = pointset->GetPointSet(timestep);
92  mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints();
93  mitk::PointSet::PointDataContainer *pointData = itkPointSet->GetPointData();
94 
95  assert(points->Size() == pointData->Size());
96 
99 
100  /* search removed points and delete the corresponding source/actor/mapper objects */
101  for (ActorMap::iterator it = m_PointActors.begin(); it != m_PointActors.end();)
102  {
103  PointIdentifier id = it->first;
104  if (!points->IndexExists(id))
105  {
106  this->RemoveEntryFromSourceMaps(id);
107  m_PropAssembly->GetParts()->RemoveItem(it->second.first); // remove from prop assembly
108  if (it->second.first != NULL)
109  it->second.first->Delete(); // Delete actor, which deletes mapper too (reference count)
110  ActorMap::iterator er = it; // save iterator for deleting
111  ++it; // advance iterator to next object
112  m_PointActors.erase(
113  er); // erase element from map. This invalidates er, therefore we had to advance it before deletion.
114  }
115  else
116  ++it;
117  }
118 
119  /* iterate over each point in the pointset and create corresponding vtk objects */
120  for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End(); ++pIt, ++pdIt)
121  {
122  PointIdentifier pointID = pIt->Index();
123  assert(pointID == pdIt->Index());
124 
125  mitk::PointSet::PointDataType data = pdIt->Value();
126 
127  ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point?
128 
129  /* Create/Update sources for the point */
130  vtkActor *a = NULL;
131  bool newPoint = (aIt == m_PointActors.end()); // current point is new
132  bool specChanged = (!newPoint && data.pointSpec != aIt->second.second); // point spec of current point has changed
133 
134  if (newPoint) // point did not exist before, we have to create vtk objects for it
135  { // create actor and mapper for the new point
136  a = vtkActor::New();
137  vtkPolyDataMapper *m = vtkPolyDataMapper::New();
138  a->SetMapper(m);
139  m->UnRegister(NULL);
140  aIt = m_PointActors.insert(std::make_pair(pointID, std::make_pair(a, data.pointSpec)))
141  .first; // insert element and update actormap iterator to point to new element
142  m_PropAssembly->AddPart(a);
143  }
144  else
145  {
146  a = aIt->second.first;
147  if (specChanged) // point exists, but point spec has changed
148  {
149  this->RemoveEntryFromSourceMaps(pointID);
150  }
151  }
152  if (newPoint || specChanged) // new point OR existing point but point spec changed
153  {
154  vtkPolyDataAlgorithm *source = NULL; // works only in VTK 5+
155  switch (data.pointSpec) // add to new map
156  { // TODO: look up representation in a representationlookuptable
157  case PTSTART: // cube
158  m_CubeSources[pointID] = vtkCubeSource::New();
159  source = m_CubeSources[pointID];
160  break;
161  case PTCORNER: // cone
162  m_ConeSources[pointID] = vtkConeSource::New();
163  source = m_ConeSources[pointID];
164  break;
165  case PTEDGE: // cylinder
166  m_CylinderSources[pointID] = vtkCylinderSource::New();
167  source = m_CylinderSources[pointID];
168  break;
169  case PTUNDEFINED: // sphere
170  case PTEND:
171  default:
172  m_SphereSources[pointID] = vtkSphereSource::New();
173  source = m_SphereSources[pointID];
174  break;
175  }
176  vtkPolyDataMapper *m = dynamic_cast<vtkPolyDataMapper *>(a->GetMapper());
177  assert(m != NULL);
178  m->SetInputConnection(source->GetOutputPort());
179  aIt->second.second = data.pointSpec; // update point spec in actormap
180  }
181  } // for each point
182 }
183 
185  vtkActor * /*actor*/)
186 {
187  this->UpdateVtkObjects();
188 
189  /* iterate over all points in pointset and apply properties to corresponding vtk objects */
190  // get and update the PointSet
191  const mitk::PointSet *pointset = this->GetInput();
192  int timestep = this->GetTimestep();
193  mitk::PointSet::DataType *itkPointSet = pointset->GetPointSet(timestep);
194  mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints();
195  mitk::PointSet::PointDataContainer *pointData = itkPointSet->GetPointData();
196  assert(points->Size() == pointData->Size());
199  mitk::DataNode *n = this->GetDataNode();
200  assert(n != NULL);
201 
202  for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End();
203  ++pIt, ++pdIt) // for each point in the pointset
204  {
205  PointIdentifier pointID = pIt->Index();
206  assert(pointID == pdIt->Index());
207 
208  mitk::PointSet::PointDataType data = pdIt->Value();
209 
210  ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point?
211  assert(aIt != m_PointActors.end()); // UpdateVtkObjects() must ensure that actor exists
212 
213  vtkActor *a = aIt->second.first;
214  assert(a != NULL);
215 
216  SetVtkMapperImmediateModeRendering(a->GetMapper());
217 
218  /* update properties */
219  // visibility
220  bool pointVisibility = true;
221  bool visValueFound = false;
222  mitk::BaseProperty *visProp = n->GetProperty("visibility", renderer);
223  mitk::BoolLookupTableProperty *visLTProp = dynamic_cast<mitk::BoolLookupTableProperty *>(visProp);
224  if (visLTProp != NULL)
225  {
226  mitk::BoolLookupTable visLookupTable = visLTProp->GetValue();
227  // if (visLookupTable != NULL)
228  //{
229  try
230  {
231  pointVisibility = visLookupTable.GetTableValue(pointID);
232  visValueFound = true;
233  }
234  catch (...)
235  {
236  }
237  //}
238  }
239  if (visValueFound == false)
240  {
241  pointVisibility = n->IsVisible(renderer, "show points"); // use BoolProperty instead
242  }
243  a->SetVisibility(pointVisibility);
244 
245  // opacity
246  float opacity = 1.0;
247  bool opValueFound = false;
248  mitk::BaseProperty *opProp = n->GetProperty("opacity", renderer);
249  mitk::FloatLookupTableProperty *opLTProp = dynamic_cast<mitk::FloatLookupTableProperty *>(opProp);
250  if (opLTProp != NULL)
251  {
252  mitk::FloatLookupTable opLookupTable = opLTProp->GetValue();
253  // if (opLookupTable != NULL)
254  //{
255  try
256  {
257  opacity = opLookupTable.GetTableValue(pointID);
258  opValueFound = true;
259  }
260  catch (...)
261  {
262  }
263  //}
264  }
265  if (opValueFound == false)
266  {
267  n->GetOpacity(opacity, renderer);
268  }
269  a->GetProperty()->SetOpacity(opacity);
271 
272  // pointsize & point position
273  float pointSize = 1.0;
274  n->GetFloatProperty("pointsize", pointSize, renderer);
275  switch (data.pointSpec)
276  { // TODO: look up representation in a representationlookuptable
277  case PTSTART: // cube
278  m_CubeSources[pointID]->SetXLength(pointSize);
279  m_CubeSources[pointID]->SetYLength(pointSize);
280  m_CubeSources[pointID]->SetZLength(pointSize);
281  // m_CubeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]);
282  break;
283  case PTCORNER: // cone
284  m_ConeSources[pointID]->SetRadius(pointSize / 2);
285  m_ConeSources[pointID]->SetHeight(pointSize);
286  m_ConeSources[pointID]->SetResolution(2); // two crossed triangles. Maybe introduce an extra property for
287  // m_ConeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]);
288  break;
289  case PTEDGE: // cylinder
290  m_CylinderSources[pointID]->SetRadius(pointSize / 2);
291  m_CylinderSources[pointID]->SetHeight(pointSize);
292  m_CylinderSources[pointID]->CappingOn();
293  m_CylinderSources[pointID]->SetResolution(6);
294  // m_CylinderSources[pointID]->SetCenter(pos[0], pos[1], pos[2]);
295  break;
296  case PTUNDEFINED: // sphere
297  case PTEND:
298  default:
299  m_SphereSources[pointID]->SetRadius(pointSize / 2);
300  m_SphereSources[pointID]->SetThetaResolution(10);
301  m_SphereSources[pointID]->SetPhiResolution(10);
302  // m_SphereSources[pointID]->SetCenter(pos[0], pos[1], pos[2]);
303  break;
304  }
305 
306  // set position
307  mitk::Point3D pos = pIt->Value();
308  aIt->second.first->SetPosition(pos[0], pos[1], pos[2]);
309 
310  // selectedcolor & color
311  float color[3];
312  if (data.selected)
313  {
314  if (!n->GetColor(color, renderer, "selectedcolor"))
315  n->GetColor(color, renderer);
316  }
317  else
318  {
319  mitk::BaseProperty *a = n->GetProperty("colorLookupTable", renderer);
321  if (b != NULL)
322  {
324  vtkLookupTable *d = c->GetVtkLookupTable();
325  double *e = d->GetTableValue(pointID);
326  color[0] = e[0];
327  color[1] = e[1];
328  color[2] = e[2];
329  }
330  else
331  {
332  if (!n->GetColor(color, renderer, "unselectedcolor"))
333  n->GetColor(color, renderer);
334  }
335  }
336 
337  // TODO: What about "color" property? 2D Mapper only uses unselected and selected color properties
338  a->GetProperty()->SetColor(color[0], color[1], color[2]);
339 
340  // TODO: label property
341  }
342  // TODO test different pointSpec
343  // TODO "line width" "show contour" "contourcolor" "contoursize" "close contour" "show label", "label"
344  // TODO "show points" vs "visibility" - is visibility evaluated at all? in a superclass maybe?
345  // TODO create lookup tables for all properties that should be evaluated per point. also create editor widgets for
346  // these lookup tables!
347  // TODO check if property changes and pointset changes are reflected in the render window immediately.
348  // TODO check behavior with large PointSets
349  // TODO check for memory leaks on adding/deleting points
350 }
351 
353 {
354  BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
355  bool needGenerateData = ls->IsGenerateDataRequired(renderer, this, GetDataNode());
356 
357  if (needGenerateData)
358  {
359  ls->UpdateGenerateDataTime();
360  this->UpdateVtkObjects();
361  }
362 
363  ApplyColorAndOpacityProperties(renderer, NULL);
364 }
365 
367 {
368  // TODO: apply new transform if time step changed
369 
370  // vtkLinearTransform * vtktransform =
371  // this->GetDataNode()->GetVtkTransform(this->GetTimestep());
372 
373  // m_SelectedActor->SetUserTransform(vtktransform);
374  // m_UnselectedActor->SetUserTransform(vtktransform);
375  // m_ContourActor->SetUserTransform(vtktransform);
376 }
377 
379  mitk::BaseRenderer *renderer,
380  bool overwrite)
381 {
382  node->AddProperty("line width", mitk::IntProperty::New(2), renderer, overwrite);
383  node->AddProperty("pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite);
384  node->AddProperty(
385  "selectedcolor", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); // yellow for selected
386  node->AddProperty(
387  "unselectedcolor", mitk::ColorProperty::New(0.5f, 1.0f, 0.5f), renderer, overwrite); // middle green for unselected
388  node->AddProperty("color", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); // red as standard
389  node->AddProperty("show contour", mitk::BoolProperty::New(false), renderer, overwrite);
390  node->AddProperty("contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite);
391  node->AddProperty("contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite);
392  node->AddProperty("show points", mitk::BoolProperty::New(true), renderer, overwrite);
393  node->AddProperty("show label", mitk::BoolProperty::New(false), renderer, overwrite);
394  node->AddProperty("label", mitk::StringProperty::New("P"), renderer, overwrite);
395  node->AddProperty("opacity", mitk::FloatProperty::New(1.0), renderer, overwrite);
396  Superclass::SetDefaultProperties(node, renderer, overwrite);
397 }
398 
400 {
401  if (o != NULL)
402  o->Delete();
403 }
404 
406 {
407  ActorMap::iterator aIt = m_PointActors.find(pointID);
408  if (aIt == m_PointActors.end())
409  return;
410 
411  switch (aIt->second.second) // erase in old map
412  { // TODO: look up representation in a representationlookuptable
413  case PTSTART: // cube
414  m_CubeSources[pointID]->Delete();
415  m_CubeSources.erase(pointID);
416  break;
417 
418  case PTCORNER: // cone
419  m_ConeSources[pointID]->Delete();
420  m_ConeSources.erase(pointID);
421  break;
422 
423  case PTEDGE: // cylinder
424  m_CylinderSources[pointID]->Delete();
425  m_CylinderSources.erase(pointID);
426  break;
427 
428  case PTUNDEFINED: // sphere
429  case PTEND:
430  default:
431  m_SphereSources[pointID]->Delete();
432  m_SphereSources.erase(pointID);
433  break;
434  }
435 }
MeshType DataType
Definition: mitkPointSet.h:133
DataType::PointsContainerIterator PointsIterator
Definition: mitkPointSet.h:137
DataType::PointDataContainer PointDataContainer
Definition: mitkPointSet.h:139
static Pointer New()
Organizes the rendering process.
struct for data of a point
Definition: mitkPointSet.h:95
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
ValueType GetTableValue(IdentifierType id) const
virtual vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
Generate the data needed for rendering into renderer.
DataType::PointIdentifier PointIdentifier
Definition: mitkPointSet.h:135
bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey="visible", bool defaultIsOn=true) const
Convenience access method for visibility properties (instances of BoolProperty). Return value is the ...
Definition: mitkDataNode.h:453
static Pointer New()
static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=NULL, bool overwrite=false)
Abstract base class for properties.
void AddProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer=nullptr, bool overwrite=false)
Add the property (instance of BaseProperty) if it does not exist (or always ifoverwrite istrue) with ...
bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey="opacity") const
Convenience access method for opacity properties (instances of FloatProperty)
The LookupTableProperty class Property to associate mitk::LookupTable to an mitk::DataNode.
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:79
virtual DataType::Pointer GetPointSet(int t=0) const
returns the pointset
mitk::PointSet::PointIdentifier PointIdentifier
void RemoveEntryFromSourceMaps(mitk::PointSet::PointIdentifier pointID)
bool GetFloatProperty(const char *propertyKey, float &floatValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for float properties (instances of FloatProperty)
virtual LookupTable * GetLookupTable()
virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer *renderer, vtkActor *actor) override
Apply color and opacity properties read from the PropertyList. Called by mapper subclasses.
static Pointer New()
DataType::PointsContainer PointsContainer
Definition: mitkPointSet.h:136
static Pointer New()
specializations of GenericLookupTable
DataType::PointDataContainerIterator PointDataIterator
Definition: mitkPointSet.h:140
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
bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="color") const
Convenience access method for color properties (instances of ColorProperty)
static Pointer New()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer) override
Set the vtkTransform of the m_Prop3D for the current time step of renderer.
virtual T GetValue() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.