Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkGizmo.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 #include "mitkGizmo.h"
18 #include "mitkGizmoInteractor.h"
19 
20 // MITK includes
21 #include <mitkBaseRenderer.h>
24 #include <mitkRenderingManager.h>
26 
27 // VTK includes
28 #include <vtkAppendPolyData.h>
29 #include <vtkCellArray.h>
30 #include <vtkCharArray.h>
31 #include <vtkConeSource.h>
32 #include <vtkCylinderSource.h>
33 #include <vtkMath.h>
34 #include <vtkPointData.h>
35 #include <vtkPoints.h>
36 #include <vtkPolyDataNormals.h>
37 #include <vtkRenderWindow.h>
38 #include <vtkSphereSource.h>
39 #include <vtkTransformPolyDataFilter.h>
40 #include <vtkTubeFilter.h>
41 
42 // ITK includes
43 #include <itkCommand.h>
44 
45 // MicroServices
46 #include <usGetModuleContext.h>
47 
48 namespace
49 {
50  const char *PROPERTY_KEY_ORIGINAL_OBJECT_OPACITY = "gizmo.originalObjectOpacity";
51 }
52 
53 namespace mitk
54 {
56  class GizmoRemover
57  {
58  public:
59  GizmoRemover() : m_Storage(nullptr), m_GizmoNode(nullptr), m_ManipulatedNode(nullptr), m_StorageObserverTag(0) {}
66  void UpdateStorageObservation(mitk::DataStorage *storage,
67  mitk::DataNode *gizmo_node,
68  mitk::DataNode *manipulated_node)
69  {
70  if (m_Storage != nullptr)
71  {
72  m_Storage->RemoveNodeEvent.RemoveListener(
73  mitk::MessageDelegate1<GizmoRemover, const mitk::DataNode *>(this, &GizmoRemover::OnDataNodeHasBeenRemoved));
74  m_Storage->RemoveObserver(m_StorageObserverTag);
75  }
76 
77  m_Storage = storage;
78  m_GizmoNode = gizmo_node;
79  m_ManipulatedNode = manipulated_node;
80 
81  if (m_Storage != nullptr)
82  {
83  m_Storage->RemoveNodeEvent.AddListener(
84  mitk::MessageDelegate1<GizmoRemover, const mitk::DataNode *>(this, &GizmoRemover::OnDataNodeHasBeenRemoved));
85 
87  command->SetCallbackFunction(this, &mitk::GizmoRemover::OnDataStorageDeleted);
88  m_StorageObserverTag = m_Storage->AddObserver(itk::ModifiedEvent(), command);
89  }
90  }
91 
93  void OnDataStorageDeleted() { m_Storage = nullptr; }
95  void OnDataNodeHasBeenRemoved(const mitk::DataNode *node)
96  {
97  if (node == m_ManipulatedNode)
98  {
99  // m_Storage is still alive because it is the emitter
100  if (m_Storage->Exists(m_GizmoNode))
101  {
102  m_Storage->Remove(m_GizmoNode);
103  // normally, gizmo will be deleted here (unless somebody
104  // still holds a reference to it)
105  }
106  }
107  }
108 
110  ~GizmoRemover()
111  {
112  if (m_Storage)
113  {
114  m_Storage->RemoveNodeEvent.RemoveListener(
115  mitk::MessageDelegate1<GizmoRemover, const mitk::DataNode *>(this, &GizmoRemover::OnDataNodeHasBeenRemoved));
116  m_Storage->RemoveObserver(m_StorageObserverTag);
117  }
118  }
119 
120  private:
121  mitk::DataStorage *m_Storage;
122  mitk::DataNode *m_GizmoNode;
123  mitk::DataNode *m_ManipulatedNode;
124  unsigned long m_StorageObserverTag;
125  };
126 
127 } // namespace MITK
128 
130 {
131  auto typeCondition = TNodePredicateDataType<Gizmo>::New();
132  auto gizmoChildren = storage->GetDerivations(node, typeCondition);
133  return !gizmoChildren->empty();
134 }
135 
137 {
138  if (node == nullptr || storage == nullptr)
139  {
140  return false;
141  }
142 
143  auto typeCondition = TNodePredicateDataType<Gizmo>::New();
144  auto gizmoChildren = storage->GetDerivations(node, typeCondition);
145 
146  for (auto &gizmoChild : *gizmoChildren)
147  {
148  Gizmo *gizmo = dynamic_cast<Gizmo *>(gizmoChild->GetData());
149  if (gizmo)
150  {
151  storage->Remove(gizmoChild);
152  gizmo->m_GizmoRemover->UpdateStorageObservation(nullptr, nullptr, nullptr);
153  }
154  }
155 
156  //--------------------------------------------------------------
157  // Restore original opacity if we changed it
158  //--------------------------------------------------------------
159  float originalOpacity = 1.0;
160  if (node->GetFloatProperty(PROPERTY_KEY_ORIGINAL_OBJECT_OPACITY, originalOpacity))
161  {
162  node->SetOpacity(originalOpacity);
163  node->GetPropertyList()->DeleteProperty(PROPERTY_KEY_ORIGINAL_OBJECT_OPACITY);
164  }
165 
166  return !gizmoChildren->empty();
167 }
168 
170 {
171  assert(node);
172  if (node->GetData() == nullptr || node->GetData()->GetGeometry() == nullptr)
173  {
174  return nullptr;
175  }
176  //--------------------------------------------------------------
177  // Add visual gizmo that follows the node to be manipulated
178  //--------------------------------------------------------------
179 
180  auto gizmo = Gizmo::New();
181  auto gizmoNode = DataNode::New();
182  gizmoNode->SetName("Gizmo");
183  gizmoNode->SetData(gizmo);
184  gizmo->FollowGeometry(node->GetData()->GetGeometry());
185 
186  //--------------------------------------------------------------
187  // Add interaction to the gizmo
188  //--------------------------------------------------------------
189 
191  interactor->LoadStateMachine("Gizmo3DStates.xml", us::GetModuleContext()->GetModule());
192  interactor->SetEventConfig("Gizmo3DConfig.xml", us::ModuleRegistry::GetModule("MitkGizmo"));
193 
194  interactor->SetGizmoNode(gizmoNode);
195  interactor->SetManipulatedObjectNode(node);
196 
197  //--------------------------------------------------------------
198  // Note current opacity for later restore and lower it
199  //--------------------------------------------------------------
200 
201  float currentNodeOpacity = 1.0;
202  if (node->GetOpacity(currentNodeOpacity, nullptr))
203  {
204  if (currentNodeOpacity > 0.5f)
205  {
206  node->SetFloatProperty(PROPERTY_KEY_ORIGINAL_OBJECT_OPACITY, currentNodeOpacity);
207  node->SetOpacity(0.5f);
208  }
209  }
210 
211  if (storage)
212  {
213  storage->Add(gizmoNode, node);
214  gizmo->m_GizmoRemover->UpdateStorageObservation(storage, gizmoNode, node);
215  }
216 
217  return gizmoNode;
218 }
219 
221  : Surface(), m_AllowTranslation(true), m_AllowRotation(true), m_AllowScaling(true), m_GizmoRemover(new GizmoRemover())
222 {
223  m_Center.Fill(0);
224 
225  m_AxisX.Fill(0);
226  m_AxisX[0] = 1;
227  m_AxisY.Fill(0);
228  m_AxisY[1] = 1;
229  m_AxisZ.Fill(0);
230  m_AxisZ[2] = 1;
231 
232  m_Radius.Fill(1);
233 
235 }
236 
238 {
239  if (m_FollowedGeometry.IsNotNull())
240  {
241  m_FollowedGeometry->RemoveObserver(m_FollowerTag);
242  }
243 }
244 
246 {
247  /* bounding box around the unscaled bounding object */
248  ScalarType bounds[6] = {-m_Radius[0] * 1.2,
249  +m_Radius[0] * 1.2,
250  -m_Radius[1] * 1.2,
251  +m_Radius[1] * 1.2,
252  -m_Radius[2] * 1.2,
253  +m_Radius[2] * 1.2};
254  GetGeometry()->SetBounds(bounds);
255  GetTimeGeometry()->Update();
256 
257  SetVtkPolyData(BuildGizmo());
258 }
259 
260 namespace
261 {
262  void AssignScalarValueTo(vtkPolyData *polydata, char value)
263  {
264  vtkSmartPointer<vtkCharArray> pointData = vtkSmartPointer<vtkCharArray>::New();
265 
266  int numberOfPoints = polydata->GetNumberOfPoints();
267  pointData->SetNumberOfComponents(1);
268  pointData->SetNumberOfTuples(numberOfPoints);
269  pointData->FillComponent(0, value);
270  polydata->GetPointData()->SetScalars(pointData);
271  }
272 
273  vtkSmartPointer<vtkPolyData> BuildAxis(const mitk::Point3D &center,
274  const mitk::Vector3D &axis,
275  double halflength,
276  bool drawRing,
277  char vertexValueAxis,
278  char vertexValueRing,
279  char vertexValueScale)
280  {
281  // Define all sizes relative to absolute size (thus that the gizmo will appear
282  // in the same relative size for huge (size >> 1) and tiny (size << 1) objects).
283  // This means that the gizmo will appear very different when a scene contains _both_
284  // huge and tiny objects at the same time, but when the users zooms in on his
285  // object of interest, the gizmo will always have the same relative size.
286  const double shaftRadius = halflength * 0.02;
287  const double arrowHeight = shaftRadius * 6;
288  const int tubeSides = 15;
289 
290  // poly data appender to collect cones and tube that make up the axis
291  vtkSmartPointer<vtkAppendPolyData> axisSource = vtkSmartPointer<vtkAppendPolyData>::New();
292 
293  // build two cones at the end of axis
294  for (double sign = -1.0; sign < 3.0; sign += 2)
295  {
296  vtkSmartPointer<vtkConeSource> cone = vtkConeSource::New();
297  // arrow tips at 110% of radius
298  cone->SetCenter(center[0] + sign * axis[0] * (halflength * 1.1 + arrowHeight * 0.5),
299  center[1] + sign * axis[1] * (halflength * 1.1 + arrowHeight * 0.5),
300  center[2] + sign * axis[2] * (halflength * 1.1 + arrowHeight * 0.5));
301  cone->SetDirection(sign * axis[0], sign * axis[1], sign * axis[2]);
302  cone->SetRadius(shaftRadius * 3);
303  cone->SetHeight(arrowHeight);
304  cone->SetResolution(tubeSides);
305  cone->CappingOn();
306  cone->Update();
307  AssignScalarValueTo(cone->GetOutput(), vertexValueScale);
308  axisSource->AddInputData(cone->GetOutput());
309  }
310 
311  // build the axis itself (as a tube around the line defining the axis)
312  vtkSmartPointer<vtkPolyData> shaftSkeleton = vtkSmartPointer<vtkPolyData>::New();
313  vtkSmartPointer<vtkPoints> shaftPoints = vtkSmartPointer<vtkPoints>::New();
314  shaftPoints->InsertPoint(0, (center - axis * halflength * 1.1).GetDataPointer());
315  shaftPoints->InsertPoint(1, (center + axis * halflength * 1.1).GetDataPointer());
316  shaftSkeleton->SetPoints(shaftPoints);
317 
318  vtkSmartPointer<vtkCellArray> shaftLines = vtkSmartPointer<vtkCellArray>::New();
319  vtkIdType shaftLinePoints[] = {0, 1};
320  shaftLines->InsertNextCell(2, shaftLinePoints);
321  shaftSkeleton->SetLines(shaftLines);
322 
323  vtkSmartPointer<vtkTubeFilter> shaftSource = vtkSmartPointer<vtkTubeFilter>::New();
324  shaftSource->SetInputData(shaftSkeleton);
325  shaftSource->SetNumberOfSides(tubeSides);
326  shaftSource->SetVaryRadiusToVaryRadiusOff();
327  shaftSource->SetRadius(shaftRadius);
328  shaftSource->Update();
329  AssignScalarValueTo(shaftSource->GetOutput(), vertexValueAxis);
330 
331  axisSource->AddInputData(shaftSource->GetOutput());
332  axisSource->Update();
333 
334  vtkSmartPointer<vtkTubeFilter> ringSource; // used after if block, so declare it here
335  if (drawRing)
336  {
337  // build the ring orthogonal to the axis (as another tube)
338  vtkSmartPointer<vtkPolyData> ringSkeleton = vtkSmartPointer<vtkPolyData>::New();
339  vtkSmartPointer<vtkPoints> ringPoints = vtkSmartPointer<vtkPoints>::New();
340  ringPoints->SetDataTypeToDouble(); // just some decision (see cast below)
341  unsigned int numberOfRingPoints = 100;
342  vtkSmartPointer<vtkCellArray> ringLines = vtkSmartPointer<vtkCellArray>::New();
343  ringLines->InsertNextCell(numberOfRingPoints + 1);
344  mitk::Vector3D ringPointer;
345  for (unsigned int segment = 0; segment < numberOfRingPoints; ++segment)
346  {
347  ringPointer[0] = 0;
348  ringPointer[1] = std::cos((double)(segment) / (double)numberOfRingPoints * 2.0 * vtkMath::Pi());
349  ringPointer[2] = std::sin((double)(segment) / (double)numberOfRingPoints * 2.0 * vtkMath::Pi());
350 
351  ringPoints->InsertPoint(segment, (ringPointer * halflength).GetDataPointer());
352 
353  ringLines->InsertCellPoint(segment);
354  }
355  ringLines->InsertCellPoint(0);
356 
357  // transform ring points (copied from vtkConeSource)
358  vtkSmartPointer<vtkTransform> t = vtkSmartPointer<vtkTransform>::New();
359  t->Translate(center.GetDataPointer());
360  double vMag = vtkMath::Norm(axis.GetDataPointer());
361  if (axis[0] < 0.0)
362  {
363  // flip x -> -x to avoid instability
364  t->RotateWXYZ(180.0, (axis[0] - vMag) / 2.0, axis[1] / 2.0, axis[2] / 2.0);
365  t->RotateWXYZ(180.0, 0, 1, 0);
366  }
367  else
368  {
369  t->RotateWXYZ(180.0, (axis[0] + vMag) / 2.0, axis[1] / 2.0, axis[2] / 2.0);
370  }
371 
372  double thisPoint[3];
373  for (unsigned int i = 0; i < numberOfRingPoints; ++i)
374  {
375  ringPoints->GetPoint(i, thisPoint);
376  t->TransformPoint(thisPoint, thisPoint);
377  ringPoints->SetPoint(i, thisPoint);
378  }
379 
380  ringSkeleton->SetPoints(ringPoints);
381  ringSkeleton->SetLines(ringLines);
382 
384  ringSource->SetInputData(ringSkeleton);
385  ringSource->SetNumberOfSides(tubeSides);
386  ringSource->SetVaryRadiusToVaryRadiusOff();
387  ringSource->SetRadius(shaftRadius);
388  ringSource->Update();
389  AssignScalarValueTo(ringSource->GetOutput(), vertexValueRing);
390  }
391 
392  // assemble axis and ring
393  vtkSmartPointer<vtkAppendPolyData> appenderGlobal = vtkSmartPointer<vtkAppendPolyData>::New();
394  appenderGlobal->AddInputData(axisSource->GetOutput());
395  if (drawRing)
396  {
397  appenderGlobal->AddInputData(ringSource->GetOutput());
398  }
399  appenderGlobal->Update();
400 
401  // make everything shiny by adding normals
402  vtkSmartPointer<vtkPolyDataNormals> normalsSource = vtkSmartPointer<vtkPolyDataNormals>::New();
403  normalsSource->SetInputConnection(appenderGlobal->GetOutputPort());
404  normalsSource->ComputePointNormalsOn();
405  normalsSource->ComputeCellNormalsOff();
406  normalsSource->SplittingOn();
407  normalsSource->Update();
408 
409  vtkSmartPointer<vtkPolyData> result = normalsSource->GetOutput();
410  return result;
411  }
412 
413 } // unnamed namespace
414 
416 {
417  double longestAxis = std::max(m_Radius[0], m_Radius[1]);
418  longestAxis = std::max(longestAxis, m_Radius[2]);
419  return longestAxis;
420 }
421 
422 vtkSmartPointer<vtkPolyData> mitk::Gizmo::BuildGizmo()
423 {
424  double longestAxis = GetLongestRadius();
425 
426  vtkSmartPointer<vtkAppendPolyData> appender = vtkSmartPointer<vtkAppendPolyData>::New();
427  appender->AddInputData(BuildAxis(m_Center,
428  m_AxisX,
429  longestAxis,
430  m_AllowRotation,
431  m_AllowTranslation ? MoveAlongAxisX : NoHandle,
432  m_AllowRotation ? RotateAroundAxisX : NoHandle,
433  m_AllowScaling ? ScaleX : NoHandle));
434  appender->AddInputData(BuildAxis(m_Center,
435  m_AxisY,
436  longestAxis,
437  m_AllowRotation,
438  m_AllowTranslation ? MoveAlongAxisY : NoHandle,
439  m_AllowRotation ? RotateAroundAxisY : NoHandle,
440  m_AllowScaling ? ScaleY : NoHandle));
441  appender->AddInputData(BuildAxis(m_Center,
442  m_AxisZ,
443  longestAxis,
444  m_AllowRotation,
445  m_AllowTranslation ? MoveAlongAxisZ : NoHandle,
446  m_AllowRotation ? RotateAroundAxisZ : NoHandle,
447  m_AllowScaling ? ScaleZ : NoHandle));
448 
449  auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
450  sphereSource->SetCenter(m_Center[0], m_Center[1], m_Center[2]);
451  sphereSource->SetRadius(longestAxis * 0.06);
452  sphereSource->Update();
453  AssignScalarValueTo(sphereSource->GetOutput(), MoveFreely);
454 
455  appender->AddInputData(sphereSource->GetOutput());
456 
457  appender->Update();
458  return appender->GetOutput();
459 }
460 
462 {
463  auto observer = itk::SimpleMemberCommand<Gizmo>::New();
464  observer->SetCallbackFunction(this, &Gizmo::OnFollowedGeometryModified);
465 
466  if (m_FollowedGeometry.IsNotNull())
467  {
468  m_FollowedGeometry->RemoveObserver(m_FollowerTag);
469  }
470 
471  m_FollowedGeometry = geom;
472  m_FollowerTag = m_FollowedGeometry->AddObserver(itk::ModifiedEvent(), observer);
473 
474  // initial adjustment
475  OnFollowedGeometryModified();
476 }
477 
479 {
480  m_Center = m_FollowedGeometry->GetCenter();
481 
482  m_AxisX = m_FollowedGeometry->GetAxisVector(0);
483  m_AxisY = m_FollowedGeometry->GetAxisVector(1);
484  m_AxisZ = m_FollowedGeometry->GetAxisVector(2);
485 
486  m_AxisX.Normalize();
487  m_AxisY.Normalize();
488  m_AxisZ.Normalize();
489 
490  for (int dim = 0; dim < 3; ++dim)
491  {
492  m_Radius[dim] = 0.5 * m_FollowedGeometry->GetExtentInMM(dim);
493  }
494 
495  UpdateRepresentation();
496 }
497 
499 {
500 #define CheckHandleType(type) \
501  if (static_cast<int>(value) == static_cast<int>(type)) \
502  return type;
503 
504  CheckHandleType(MoveFreely);
505  CheckHandleType(MoveAlongAxisX);
506  CheckHandleType(MoveAlongAxisY);
507  CheckHandleType(MoveAlongAxisZ);
508  CheckHandleType(RotateAroundAxisX);
509  CheckHandleType(RotateAroundAxisY);
510  CheckHandleType(RotateAroundAxisZ);
511  CheckHandleType(ScaleX);
512  CheckHandleType(ScaleY);
513  CheckHandleType(ScaleZ);
514  return NoHandle;
515 #undef CheckHandleType
516 }
517 
519 {
520  assert(GetVtkPolyData());
521  assert(GetVtkPolyData()->GetPointData());
522  assert(GetVtkPolyData()->GetPointData()->GetScalars());
523  double dataValue = GetVtkPolyData()->GetPointData()->GetScalars()->GetTuple1(id);
524  return GetHandleFromPointDataValue(dataValue);
525 }
526 
528 {
529 #define CheckHandleType(candidateType) \
530  if (type == candidateType) \
531  return std::string(#candidateType);
532 
533  CheckHandleType(MoveFreely);
534  CheckHandleType(MoveAlongAxisX);
535  CheckHandleType(MoveAlongAxisY);
536  CheckHandleType(MoveAlongAxisZ);
537  CheckHandleType(RotateAroundAxisX);
538  CheckHandleType(RotateAroundAxisY);
539  CheckHandleType(RotateAroundAxisZ);
540  CheckHandleType(ScaleX);
541  CheckHandleType(ScaleY);
542  CheckHandleType(ScaleZ);
543  CheckHandleType(NoHandle);
544  return "InvalidHandleType";
545 #undef CheckHandleType
546 }
virtual ~Gizmo()
Definition: mitkGizmo.cpp:237
virtual void Add(mitk::DataNode *node, const mitk::DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is NULL, the BaseRenderer-independent PropertyList ...
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
HandleType GetHandleFromPointID(vtkIdType id)
Definition: mitkGizmo.cpp:518
virtual SetOfObjects::ConstPointer GetDerivations(const mitk::DataNode *node, const NodePredicateBase *condition=nullptr, bool onlyDirectDerivations=true) const =0
returns a set of derived objects for a given node.
double ScalarType
static DataNode::Pointer AddGizmoToNode(DataNode *node, DataStorage *storage)
Definition: mitkGizmo.cpp:169
static Module * GetModule(long id)
DataCollection - Class to facilitate loading/accessing structured data.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
static Pointer New()
#define CheckHandleType(type)
static bool HasGizmoAttached(mitk::DataNode *node, DataStorage *storage)
Definition: mitkGizmo.cpp:129
bool DeleteProperty(const std::string &propertyKey)
Remove a property from the list/map.
void FollowGeometry(BaseGeometry *geom)
Definition: mitkGizmo.cpp:461
HandleType
Names for the different parts of the gizmo.
Definition: mitkGizmo.h:65
void SetFloatProperty(const char *propertyKey, float floatValue, const mitk::BaseRenderer *renderer=nullptr)
Convenience method for setting float properties (instances of FloatProperty)
bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey="opacity") const
Convenience access method for opacity properties (instances of FloatProperty)
void SetOpacity(float opacity, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="opacity")
Convenience method for setting opacity properties (instances of FloatProperty)
static Pointer New()
bool GetFloatProperty(const char *propertyKey, float &floatValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for float properties (instances of FloatProperty)
double GetLongestRadius() const
Return the longest of the three axes.
Definition: mitkGizmo.cpp:415
static T max(T x, T y)
Definition: svm.cpp:70
static Pointer New()
void UpdateRepresentation()
Updates the representing surface object after changes to center, axes, or radius. ...
Definition: mitkGizmo.cpp:245
mitk::Gizmo::HandleType GetHandleFromPointDataValue(double value)
Definition: mitkGizmo.cpp:498
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
vtkSmartPointer< vtkPolyData > BuildGizmo()
Creates a vtkPolyData representing the parameters defining the gizmo.
Definition: mitkGizmo.cpp:422
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void OnFollowedGeometryModified()
The ITK callback to receive modified events of the followed geometry.
Definition: mitkGizmo.cpp:478
static std::string HandleTypeToString(HandleType type)
Conversion for any kind of logging/debug/... purposes.
Definition: mitkGizmo.cpp:527
BaseGeometry Describes the geometry of a data object.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
static bool RemoveGizmoFromNode(DataNode *node, DataStorage *storage)
Definition: mitkGizmo.cpp:136
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.